微信小程序手写时间间隔组件,可设置间隔时间一分钟,半小时,一小时的间隔

news2024/11/26 2:54:40

纯手写时间间隔组件

需求:小程序中可以根据时间段进行选择开始时间和结束时间,如:当前时间是09:00,
则我可以从9点开始选择时间,每半个小时为间隔,那么下一个时间就算9:30,10:00,依次类推
就像element-ui中有个时间选择器就可以根据自己设置的时间间隔去选择,可以0.5小时,1小时或者2.5小时的间隔进行选择
由于公司小程序用的是vant-ui来开发的,我去找vant的时间组件,发现没有这样的,所以决定自己开发一下这个组件

这是element-ui的选择时间

!!!注意:

由于公司用的是vant,所以弹窗按钮用的都是我们用vant自己封装的组件,
在这里就不展示弹窗组件还有按钮了,弹窗和按钮就得大家自己用自己的框架去显示了

看效果

在这里插入图片描述在这里插入图片描述
间隔一小时
在这里插入图片描述
提前30分钟和推迟30分钟 当前时间10:51
在这里插入图片描述在这里插入图片描述

创建 time-interval组件 如果你想全局使用则在app.json的usingComponents中添加你得组件地址

 "usingComponents": {"time-interval": "/components/time-interval/time-interval"}

创建好后就开始编码 HTML部分

<!-- 这个是我们自己封装的按钮组件 -->
<import src="../../static/templates/template.wxml"></import>
<!-- 工具类 -->
<wxs src="./util.wxs" module="computed" />
<!-- 这个是自己封装的弹窗组件 -->
<custom-popup
    customStyle="width: 100%;max-height: calc(100% - 148rpx); overflow: hidden; border-radius: 24rpx 24rpx 0 0;"
    hidden="{{!isShowTime}}" isShowPopup="{{isShowTime}}" title="{{title}}"
    isCloseOnClickOverlay="{{isCloseOnClickOverlay}}" bindhidePopup="hidePopup" bind:titleTap="titleTap">
<!-- 具体的时间间隔代码如下 -->
    <view class="w-time_container">
        <view class="w-t_left" data-type="startOptions" bind:touchstart="onTouchStart" catch:touchmove="onTouchMove"
            bind:touchend="onTouchEnd" bind:touchcancel="onTouchEnd">
            <view
                style="{{ computed.wrapperStyle({ offset:startOptions.offset, itemHeight, visibleItemCount, duration:startOptions.duration }) }}">
                <view class="w-time_row {{index===startOptions.currentIndex?'w-check_box':''}}"
                    style="height: {{ itemHeight }}px" wx:for="{{timeList}}" wx:key="index" data-item="{{item}}"
                    data-index="{{ index }}" data-type="startOptions" bind:tap="onClickItem">
                    {{item.time}}
                </view>
            </view>
        </view>
        <view class="w-t_right" data-type="endOptions" bind:touchstart="onTouchStart" catch:touchmove="onTouchMove"
            bind:touchend="onTouchEnd" bind:touchcancel="onTouchEnd">
            <view
                style="{{ computed.wrapperStyle({ offset:endOptions.offset, itemHeight, visibleItemCount, duration:endOptions.duration }) }}">
                <view
                    class="w-time_row {{index===endOptions.currentIndex?'w-check_box':''}} {{startTime.timeStamp>=item.timeStamp?'w-disabled':''}}"
                    wx:for="{{timeList}}" wx:key="index" data-item="{{item}}" data-index="{{ index }}"
                    data-type="endOptions" bind:tap="{{startTime.timeStamp>=item.timeStamp?'':'onClickItem'}}">
                    {{item.time}}
                </view>
            </view>

        </view>
        <view class="w-pick_mask" style="background-size: 100% 40%;"></view>
    </view>
    <!-- 这个是按钮组件 -->
    <template is="iconBtn" data="{{btnText: '确定', btnTap: 'confirmTime'}}"></template>
</custom-popup>

js部分


/**
 * 获取当前天时间
 * @param param 【Y:年;M:月;D:日;h:小时;m:分钟;s:秒;】 默认精确到秒
 * @returns {*}
 */
function getCurrentDate(param = 's', target = '') {
    var now = target ? new Date(toIosDate(target)) : new Date();
    var year = now.getFullYear(); //得到年份
    var month = now.getMonth(); //得到月份
    var date = now.getDate(); //得到日期
    var day = now.getDay(); //得到周几
    var hour = now.getHours(); //得到小时
    var minu = now.getMinutes(); //得到分钟
    var sec = now.getSeconds(); //得到秒
    month = month + 1;
    if (month < 10) month = "0" + month;
    if (date < 10) date = "0" + date;
    if (hour < 10) hour = "0" + hour;
    if (minu < 10) minu = "0" + minu;
    if (sec < 10) sec = "0" + sec;

    const arr = {
        'Y': year,
        'M': year + "-" + month,
        'D': year + "-" + month + "-" + date,
        'h': year + "-" + month + "-" + date + " " + hour,
        'm': year + "-" + month + "-" + date + " " + hour + ":" + minu,
        's': year + "-" + month + "-" + date + " " + hour + ":" + minu + ":" + sec
    }
    return {
        year,
        month,
        day: date,
        hour,
        minu,
        sec,
        date: arr[param]
    };
}

function range(num, min, max) {
    return Math.min(Math.max(num, min), max);
}

function isObj(x) {
    const type = typeof x;
    return x !== null && (type === 'object' || type === 'function');
}
const DEFAULT_DURATION = 200;
let app = getApp();
let isIOS = /ios/ig.test(app.globalData.systemInfo.system);
/**
 * 判断是否是iso,ios的话时间格式会有问题得2023/09/13,以斜杠的格式传入
 * @param {时间} date 
 */
function toIosDate(date) {
    return isIOS ? date.replace(/-/g, '/') : date
}
Component({
    options: {
        addGlobalClass: true,
        styleIsolation: "apply-shared"
    },
    /**
     * 组件的属性列表
     */
    properties: {
        // 是否显示
        isShowTime: {
            type: Boolean,
            value: false,
            observer: 'initArr'
        },
        // 标题
        title: {
            type: String,
            value: '选择时间'
        },
        // 点击蒙层是否关闭弹窗
        isCloseOnClickOverlay: {
            type: Boolean,
            value: false
        },
        //间隔时间
        intervalTime: {
            type: Number,
            value: 1/60, //单位小时
        },
        //是否是推迟还是提前多少分钟 提前则大于0,推迟则小于0,且不能大于一天
        hasDelay: {
            type: Number,
            value: 0, //单位分钟
        },
        //选择的日期,默认当天的日期
        curDate: {
            type: String,
            valeu: getCurrentDate('D').date
        },
        //可见的选项个数
        visibleItemCount: {
            type: Number,
            value: 6
        },
        //选项高度
        itemHeight: {
            type: Number,
            value: 44
        }
    },

    /**
     * 组件的初始数据
     */
    data: {
        startTime: {},
        endTime: {},
        timeList: [],
        startOptions: {
            startY: 0,
            startOffset: 0,
            duration: 0,
            offset: 0,
            currentIndex: 0
        },
        endOptions: {
            startY: 0,
            startOffset: 0,
            duration: 0,
            offset: 0,
            currentIndex: 0
        }
    },


    /**
     * 组件的方法列表
     */
    methods: {
        initArr(nv, ov) {
            if (nv) {
                const {
                    date,
                    hour,
                    minu,
                } = getCurrentDate('D')
                const w_date = this.properties.curDate ? (date === this.properties.curDate ? '' : `${this.properties.curDate} 00:00`) : `${date} ${hour}:${minu}`

                this.setData({
                    timeList: this.createTime(getCurrentDate('D', w_date), this.properties.intervalTime)
                })
                this.setIndex(0, 'startOptions');
                this.setIndex(1, 'endOptions');
            }
        },
        createTime(target, h = 1) {
            const {
                hour,
                minu,
                date
            } = target
            const e_date = this.getRecentDate(1, this.properties.curDate)
            let arr = []
            let startStamp = new Date(toIosDate(date + ` ${hour}:${minu}`)).getTime()
            //是否是推迟还是提前多少分钟
            if (Math.abs(this.properties.hasDelay) > 0) {
                startStamp = startStamp + this.properties.hasDelay*60*1000
            } 
            const endStamp = new Date(toIosDate(e_date + ' 00:00')).getTime()

            for (let i = startStamp; i < endStamp; i += (h * 60 * 60 * 1000)) {
                const res = this.formatDate(i)
                arr.push({
                    time: res.time,
                    date: res.date,
                    dateM: res.dateM,
                    timeStamp: i,
                    disabled: false
                })

            }
            return arr
        },
        confirmTime() {
            if (!this.data.endTime.timeStamp) {
                return wx.showToast({
                    title: '请选择结束时间',
                    icon: 'none',
                })
            }

            this.triggerEvent('chooseInterver', {
                startTime: this.data.startTime,
                endTime: this.data.endTime
            })
        },

        //时间戳转换
        formatDate(target) {
            const date = new Date(target)
            let year = date.getFullYear();
            let months = date.getMonth() + 1;
            let month = (months < 10 ? '0' + months : months).toString();
            let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
            let hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
            let min = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
            let sec = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
            return {
                year: year.toString(),
                month,
                day,
                hours,
                min,
                sec,
                time: hours + ":" + min,
                date: year + "-" + month + "-" + day + " " + hours + ":" + min,
                dateM: year + "-" + month + "-" + day
            }
        },
  //计算当前时间几天后的数据
        getRecentDate(day, target) {
            var date1 = target ? new Date(toIosDate(target)) : new Date(),
                time1 = date1.getFullYear() + "-" + (date1.getMonth() + 1) + "-" + date1.getDate(); //time1表示当前时间
            var date2 = new Date(date1);
            date2.setDate(date1.getDate() + day);
            const y = date2.getFullYear();
            const m = (date2.getMonth() + 1) > 9 ? (date2.getMonth() + 1) : '0' + (date2.getMonth() + 1)
            const d = date2.getDate() > 9 ? date2.getDate() : '0' + date2.getDate()
            let h = date2.getHours() < 10 ? '0' + date2.getHours() : date2.getHours();
            let n = date2.getMinutes() < 10 ? '0' + date2.getMinutes() : date2.getMinutes();
            let s = date2.getSeconds() < 10 ? '0' + date2.getSeconds() : date2.getSeconds();
            return y + "-" + m + "-" + d;
        },
        hidePopup() {
            this.setData({
                [`startOptions.startY`]: 0,
                [`startOptions.startOffset`]: 0,
                [`startOptions.duration`]: 0,
                [`startOptions.currentIndex`]: 0,
                [`endOptions.startY`]: 0,
                [`endOptions.startOffset`]: 0,
                [`endOptions.duration`]: 0,
                [`endOptions.currentIndex`]: 0,
            })
            this.triggerEvent('close')
        },
        titleTap() {
            this.triggerEvent('titleTap')
        },
        getCount() {
            return this.data.timeList.length;
        },
        onTouchStart(event) {
            const options = event.currentTarget.dataset.type
            this.setData({
                [`${options}.startY`]: event.touches[0].clientY,
                [`${options}.startOffset`]: this.data[options].offset,
                [`${options}.duration`]: 0,
            });
        },
        onTouchMove(event) {
            const options = event.currentTarget.dataset.type
            const deltaY = event.touches[0].clientY - this.data[options].startY;
            this.setData({
                [`${options}.offset`]: range(
                    this.data[options].startOffset + deltaY,
                    -(this.getCount() * this.properties.itemHeight),
                    this.properties.itemHeight
                ),
            });
        },

        onTouchEnd(event) {
            const options = event.currentTarget.dataset.type
            if (this.data[options].offset !== this.data[options].startOffset) {
                this.setData({
                    [`${options}.duration`]: DEFAULT_DURATION
                });

                const index = range(
                    Math.round(-this.data[options].offset / this.data.itemHeight),
                    0,
                    this.getCount() - 1
                );
                this.setIndex(index, options);
            }
        },

        onClickItem(event) {
            const options = event.currentTarget.dataset.type
            const {
                index
            } = event.currentTarget.dataset;
            this.setIndex(index, options);
        },

        /**
         * 设置位置
         * @param {*} index 数组下标 位置
         * @param {*} options 数据类型
         */
        setIndex(index, options) {
            const {
                data
            } = this;
            index = this.adjustIndex(index) || 0;
            const offset = -index * this.properties.itemHeight;
            if (index !== data[options].currentIndex) {
                this.setData({
                    [`${options}.offset`]: offset,
                    [`${options}.currentIndex`]: index,
                    [`${options==='startOptions'?'startTime':'endTime'}`]: this.data.timeList[index]
                })
                //判断结束时间是否大于开始时间,是则选择否则为空
                if (options === 'endOptions') {
                    if (this.data.startTime.timeStamp < this.data.timeList[index].timeStamp) {
                        this.setData({
                            endTime: this.data.timeList[index]
                        })
                    } else {
                        this.setData({
                            endTime: {}
                        })
                    }
                }else{
                    this.setData({
                        endTime: {}
                    })
                }
                
            } else {
                this.setData({
                    [`${options}.offset`]: offset,
                    [`${options==='startOptions'?'startTime':'endTime'}`]: this.data.timeList[index]
                });
            }
        },
        adjustIndex(index) {
            const count = this.getCount();

            index = range(index, 0, count);
            for (let i = index; i < count; i++) {
                if (!this.isDisabled(this.data.timeList[i])) return i;
            }
            for (let i = index - 1; i >= 0; i--) {
                if (!this.isDisabled(this.data.timeList[i])) return i;
            }
        },
        isDisabled(option) {
            return isObj(option) && option.disabled;
        },
    }
})

css 部分

.w-time_container {
    position: relative;
    height: 600rpx;
    width: 100%;
    padding: 8rpx;
    box-sizing: border-box;
    display: flex;
}

.w-t_left,
.w-t_right {
    width: 50%;
    height: 100%;
    display: flex;
    padding: 48rpx 0;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;
    overflow: hidden;
}

.w-pick_mask{
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4)), linear-gradient(0deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4));
    background-repeat: no-repeat;
    background-position: top, bottom;
    transform: translateZ(0);
    pointer-events: none;
}


.w-time_row {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 32rpx;
    font-weight: 600;
    box-sizing: border-box;
}

.w-check_box {
    color: #264AFF;
}
.w-disabled {
    color: #0A1B33B3;
}

工具类util.wxs

function addUnit(value) {
    if (value == null) {
        return undefined;
    }
    var REGEXP1 = getRegExp('^-?\d+(\.\d+)?$');
    return REGEXP1.test('' + value) ? value + 'px' : value;
}
var REGEXP2 = getRegExp('{|}|"', 'g');

function keys(obj) {
    return JSON.stringify(obj)
        .replace(REGEXP2, '')
        .split(',')
        .map(function (item) {
            return item.split(':')[0];
        });
}

function kebabCase(word) {
    var newWord = word
        .replace(getRegExp("[A-Z]", 'g'), function (i) {
            return '-' + i;
        })
        .toLowerCase()

    return newWord;
}


function isArray(array) {
    return array && array.constructor === 'Array';
}

function style(styles) {
    if (isArray(styles)) {
        return styles
            .filter(function (item) {
                return item != null && item !== '';
            })
            .map(function (item) {
                return style(item);
            })
            .join(';');
    }

    if ('Object' === styles.constructor) {
        return keys(styles)
            .filter(function (key) {
                return styles[key] != null && styles[key] !== '';
            })
            .map(function (key) {
                return [kebabCase(key), [styles[key]]].join(':');
            })
            .join(';');
    }

    return styles;
}

function wrapperStyle(data) {
    var offset = addUnit(
        data.offset + (data.itemHeight * (data.visibleItemCount - 1)) / 2
    );
    return style({
        transition: 'transform ' + data.duration + 'ms',
        'line-height': addUnit(data.itemHeight),
        transform: 'translate3d(0, ' + offset + ', 0)',
    });
}

module.exports = {
    wrapperStyle: wrapperStyle,
};

Attributes

参数说明类型可选值默认值
intervalTime间隔时间(单位小时)Number1/60(一分钟);30/60(30分钟); 1(1小时);2.5(两个半小时)1/60
hasDelay是否是推迟还是提前多少分钟 提前则大于0,推迟则小于0,且不能大于一天Number10(提前10分钟);-10(推迟10分钟)0
curDate选择的日期,默认当天的日期String2023-02-11或 2023-02-11 09:00:00当天时间

Events

参数说明类型参数返回值
chooseInterver选择时间结果Function-{starTime:resultTime,endTime:resultTime}

resultTime

prop说明
date日期+时分 2023-09-13 09:33
dateM日期没有时分 2023-09-13
time选择的时分 09:33
timeStamp选择date的时间戳 1694568780000

看过vant源码的会发现 我这里会有一部分vant的代码,确实是,我用了一下vant的时间选择器的样式代码,没办法时间紧迫写的样式达不到那种丝滑,只能凑合用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1020216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue基础知识十三:Vue中的$nextTick有什么作用?

一、NextTick是什么 官方对其的定义 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法&#xff0c;获取更新后的 DOM 什么意思呢&#xff1f; 我们可以理解成&#xff0c;Vue 在更新 DOM 时是异步执行的。当数据发生变化&#xff0c;Vue将开启一个异…

阿里测试岗:惨不忍睹的三面,幸好做足了准备,月薪17k,已拿offer....

我今年25岁&#xff0c;专业是电子信息工程本科&#xff0c;19年年末的时候去面试&#xff0c;统一投了测试的岗位&#xff0c;软件硬件都有&#xff0c;那时候面试的两家公司都是做培训的&#xff0c;当初没啥钱&#xff0c;他们以面试为谎言再推荐去培训这点让我特别难受。 …

开启编程之门

自我介绍 目前已经大二了&#xff0c;计算机专业在读&#xff0c;是一个热爱编程&#xff0c;做事踏实专注的人。转眼间一年已经过去了&#xff0c;也接触编程一年了&#xff0c;但开始并没有对所学所想进行很好的总结和输出&#xff0c;这一年也有了新的很多感悟与心得&#x…

JVM——5.类文件结构

这篇文章我们来讲一下jvm的类文件结构 目录 1.引言 2.类文件结构概论 3.魔数与class文件的版本 4.常量池 5.访问标志 6.类索引、父类索引与接口索引集合 7.字段表集合 8.方法表集合 9.属性表集合 9.1code属性 9.2 Exception属性 10小结 1.引言 代码编译的结果从本…

vue学习-02vue入门之组件

删除Vue-cli预设 在用户根目录下(C:\Users\你的用户名)这个地址里有一个.vuerc 文件,修改或删除配置 组件 Props(组件之间的数据传递) Prop 的大小写 (camelCase vs kebab-case)不敏感Prop 类型: String Number Boolean Array Object Date Function Symbol传递静态或动态 Pr…

「聊设计模式」之抽象工厂模式(Abstract Factory)

&#x1f3c6;本文收录于《聊设计模式》专栏&#xff0c;专门攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎持续关注&&收藏&&订阅&#xff01; 前言 在软件开发中&#xff0c;设计模式是一种被广泛使用的经验…

kudu 1.4.0 离线安装

1.准备rpm安装包 kudu-1.4.0: kudu的基础安装包 kudu-client0-1.4.0: kudu的c++客户端共享库 kudu-client-devel-1.4.0: kudu的c++客户端共享库sdk kudu-master-1.4.0: kudu master kudu-tserver-1.4.0: kudu tserver

任意输入一个整数m,若m不是素数,则对m进行质因数分解,并以质因数从小到大顺序排列的乘积形式输出

每个合数都可以写成几个质数&#xff08;也可称为素数&#xff09;相乘的形式 &#xff0c;这几个质数就都叫做这个合数的质因数。 #include <stdio.h> int isPrime(int num)// 判断一个数是否是素数 {if (num < 2) {return 0;}for (int i 2; i * i < num; i) {…

汽车电子 -- CAN总线波特率计算方法

上一篇文章介绍 PCAN View 安装与使用 的时候&#xff0c;留下了两个问题&#xff0c;CAN总线波特率该怎么计算&#xff1f; 下图里的这些 Prescaler、tseg1、tseg2、sync Jump Width是什么意思&#xff1f; CAN2.0协议中定义标称位速率为一理想的发送器在没有重新同步的情况…

2023年毫米波行业研究报告

第一章 行业概况 1.1 定义 毫米波是一种电磁波&#xff0c;其波长范围在1毫米至10毫米之间&#xff0c;频率介于30GHz至300GHz。与sub-6G (6GHz以下频段&#xff09;的5G系统相比&#xff0c;5G毫米波通信在带宽、时延和灵活弹性空口配置方面具有明显优势。这使其能够有效地满…

风车时间锁管理 - 构建IPA文件加锁+签名+管理一站式解决方案

时间锁管理&#xff1a;是一种用于控制对某些资源、功能或操作的访问权限的机制&#xff0c;它通过设定时间限制来限制对特定内容、系统或功能的访问或执行&#xff0c;以提高安全性和控制性&#xff0c;时间锁管理常见于以下场景&#xff1a; 1. 文件或文档的保密性&#xff…

STL list

文章目录 一、list 类的模拟实现 list 是一个带头双向循环链表&#xff0c;可以存储任意类型 模板参数 T 表示存储元素的类型&#xff0c;Alloc 是空间配置器&#xff0c;一般不用传 一、list 类的模拟实现 iterator 和 const_iterator 除了下述不同外&#xff0c;其他代码基…

优优嗨聚集团:抖音外卖转为区域代理,美团外卖是否胜利

在外卖市场日益激烈的竞争中&#xff0c;抖音和美团两大巨头都有着不同的策略。近期&#xff0c;抖音外卖宣布转为区域代理模式&#xff0c;而美团外卖则持续扩大市场份额。 外卖市场近年来呈现出爆炸性增长&#xff0c;成为消费者日常生活中不可或缺的一部分。根据艾媒咨询数据…

Unity之手游UI的点击和方向移动

一 Button的点击 1.1 新建UI -> Button 1.2 在Button上面右击添加空物体 1.3 创建脚本挂载到空物体上面 脚本内容添加点击方法&#xff0c;来控制物体的显示隐藏 using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using Unit…

Keepalived+LVS负载均衡

Keepalived 是一个用于实现高可用性的开源软件&#xff0c;它基于 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff09;协议&#xff0c;允许多台服务器协同工作&#xff0c;以确保在某个服务器出现故障时服务的连续性。Keepalived 的核心思想是将多台服务器配置成…

剑指offer(C++)-JZ67:把字符串转换成整数atoi(算法-模拟)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 写一个函数 StrToInt&#xff0c;实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。…

8种LED显示屏的安装方式

LED显示屏可以根据不同的应用需求和场地条件采用多种安装方式。 LED显示屏的常见安装方式包括&#xff1a; 立柱式&#xff1a;一般多用于大厦门口、大楼大厅等户外场所&#xff0c;可以抵抗风雨侵蚀&#xff0c;更适用于户外广告牌的使用。安装方式有单立柱安装、双立柱安装和…

联合matlab和Arcgis进行netcdf格式的雪覆盖数据的重新投影栅格

图片摘要 本专栏目的是将netcdf格式的雪覆盖数据进行重新投影&#xff0c;需要使用的工具包括matlab和Arcgis&#xff0c;下面进入正题。 1.数据的下载与读取---matlab 最近我需要读取北半球的冰雪覆盖数据&#xff0c;下载的是MODIS/Terra Snow Cover Monthly L3 Global 0.0…

CPU的各种存储器接口

设计电路时往往绕不开要做一些内存或者外存的接口设计&#xff0c;比如接SDRAM、NAND FLASH等等。这些无非是为了扩展原来CPU的内存或者外存资源&#xff0c;方便运行更大的系统。比较常见的就是一些Linux的核心板。I.MX6这个就是很多产品设计中使用的。 那么&#xff0c;在这些…

uniapp 可输入可选择的........框

安装 uniapp: uni-combox地址 vue页面 <uni-combox :border"false" input"selectname" focus"handleFocus" blur"handleBlur" :candidates"candidates" placeholder"请选择姓名" v-model"name"&g…