首頁 > 軟體

微信小程式自定義時間段picker選擇器

2022-07-11 10:00:25

本文範例為大家分享了微信小程式自定義時間段picker選擇器的具體程式碼,供大家參考,具體內容如下

想實現一個可以選擇年份和時間段的日期選擇器,如下所示

微信小程式自帶的picker元件雖然能實現如上的內容,但不能實現樣式的修改,不太符合小程式的設計主題,所以考慮了以下兩種方法來實現如上的設計。

1.自定義date-picker

把要實現的date-picker封裝為一個元件,元件內套用小程式自帶的picker-view元件,其中picker_view-column表示不同的選擇列,這樣可以方便地實現樣式的自定義。

實現效果:

具體實現

wxml檔案:

<view class="mask" wx:if="{{isShow}}" catchtap="cancel">
  <view class="content" style="height:800rpx" animation="{{animation}}">
    <view class="top">
      <view class="top-text top-left-color" hover-class="top-left-color-hover" catchtap="cancel">取消</view>
      <view class="top-text top-right-color" hover-class="top-right-color-hover" catchtap="confirm">確定</view>
    </view>
    <picker-view style="width: 100%; height: 80%;" value="{{value}}" bindchange="change" catchtap="no">
      <picker-view-column>
        <view wx:for="{{date_list}}" wx:key="date_list" class="item">{{item}}</view>
      </picker-view-column>
      <picker-view-column>
        <view wx:for="{{time_list}}" wx:key="time_list" class="item">{{item}}</view>
      </picker-view-column>
    </picker-view>
  </view>
</view>

wxss檔案:

.mask {
  position: fixed;
  width: 100%;
  height: 100%;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  display: flex;
  background-color: rgba(0, 0, 0, 0.7);
  z-index: 9999;
  flex-direction: column;
  justify-content: flex-end;
}

.content {
  display: flex;
  flex-direction: column;
  width: 100%;
  background: white;
  border-top-right-radius: 20rpx;
  border-top-left-radius: 20rpx;
}

.top {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  height: 100rpx;
  border-bottom: 1rpx solid #d3cfcf;
}

.top-text {
  font-size: 30rpx;
  width: 150rpx;
  height: 100rpx;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

.top-left-color {
  color: #878787;
}

.top-left-color-hover {
  color: #f1eaea;
}

.top-right-color {
  color: #1296DB;
}

.top-right-color-hover {
  color: #82ccf3;
}

.item {
  width: 100%;
  align-items: center;
  justify-content: center;
  display: flex;
  flex-direction: row;
  font-size: 18px;
}
Component({
    /**
     * 元件的屬性列表
     */
    properties: {
        range: { //可預約的日期範圍。預設日期從今天開始,到第range天后為止,這裡設為10天
            type: Number,
            value: 10
        },
        start_time: { //開始時間,設為整點
            type: Number,
            value: 8
        },
        step: { //預約時間的步長,設定為30,表示30分鐘
            type: Number
        },
        end_time: { //結束時間,設為整點
            type: Number,
            value: 22
        }
    },

    /**
     * 元件的初始資料
     */
    data: {
        isShow: false,
        selectDate: "",
        dialogh: 0,

        //日期列表和時間列表
        date_list: [],
        time_list: []
    },
    attached: function () {
        let start_day = this.ts_string(new Date().getTime());
        console.log(start_day); //2021-08-31
        console.log(new Date());
        let end_day = this.ts_string(new Date().setDate(new Date().getDate() + this.properties.range))
        //獲取日期列表
        let date_list = this.getDiffDate(start_day, end_day);
        //獲取時間列表
        let time_list = this.getTimeList(this.properties.start_time, this.properties.end_time, this.properties.step);
        console.log(time_list);
        this.setData({
            // date_time: [date_column, time_column],
            date_list: date_list,
            time_list: time_list,
        })
        //動畫
        this.animation = wx.createAnimation({
            duration: 300
        })
        //500rpx轉成px
        let dialoghpx = 800 / 750 * wx.getSystemInfoSync().windowWidth
        this.setData({
            dialogh: dialoghpx,
            selectDate: this.data.date_list[0] + this.data.time_list[0]
        })
    },
    methods: {
        getDiffDate(start, end) {
            let startTime = new Date(start);
            let endTime = new Date(end);
            let dateArr = [];
            while ((endTime.getTime() - startTime.getTime()) >= 0) {
                dateArr.push(this.ts_string(startTime.getTime()));
                startTime.setDate(startTime.getDate() + 1);
            }
            return dateArr;
        },
        zfill(num, length) {
            return (Array(length).join('0') + num).slice(-length);
        },
        //把日期轉換成xxxx-xx-xx的形式
        ts_string(timestamp) {
            let d = new Date(timestamp);
            let day = "";
            switch (d.getDay()) {
                case 1:
                    day = "週一";
                    break;
                case 2:
                    day = "週二";
                    break;
                case 3:
                    day = "週三";
                    break;
                case 4:
                    day = "週四";
                    break;
                case 5:
                    day = "週五";
                    break;
                case 6:
                    day = "週六";
                    break;
                case 0:
                    day = "週日";
                    break;
            }
            let string = (d.getFullYear()) + "-" +
                this.zfill((d.getMonth() + 1), 2) + "-" +
                this.zfill((d.getDate()), 2) + " (" + day + ")"
            return string
        },
        //獲取時間區間列表,輸入(起始時間,結束時間,步長)
        getTimeList(start, end, step) {
            let start_time = new Date();
            //設定起始時間
            start_time.setHours(start, 0, 0);
            console.log(start_time);
            //設定結束時間
            let end_time = new Date();
            end_time.setHours(end, 0, 0);
            let startG = start_time.getTime(); //起始時間的格林時間
            let endG = end_time.getTime(); //起始時間的格林時間
            let step_ms = step * 60 * 1000;
            let timeArr = [];
            while (startG < endG) {
                let time = this.timeAdd(startG, step_ms);
                timeArr.push(time);
                startG += step_ms;
            }

            return timeArr;
        },
        timeAdd(time1, add) {
            var nd = new Date(time1); //建立時間物件
            //獲取起始時間的時分秒
            var hh1 = nd.getHours();
            var mm1 = nd.getMinutes();
            if (hh1 <= 9) hh1 = "0" + hh1;
            if (mm1 <= 9) mm1 = "0" + mm1;
            nd = nd.valueOf(); //轉換為毫秒數
            nd = nd + Number(add);
            nd = new Date(nd);
            var hh2 = nd.getHours();
            var mm2 = nd.getMinutes();
            if (hh2 <= 9) hh2 = "0" + hh2;
            if (mm2 <= 9) mm2 = "0" + mm2;
            var time = hh1 + ":" + mm1 + "-" + hh2 + ":" + mm2;
            return time; //時間段
        },
        change: function (e) {
            const val = e.detail.value;
            //val[0]表示選擇的第一列序號,val[1]表示選擇的第二列序號
            let select = this.data.date_list[val[0]] + this.data.time_list[val[1]]
            console.log(select);
            this.setData({
                selectDate: select
            })

        },
        showDialog() {
            this.setData({
                isShow: true
            })
            //先向下移動dialog高度,然後恢復原位從而形成從下向上彈出效果
            this.animation.translateY(this.data.dialogh).translateY(0).step()
            this.setData({
                animation: this.animation.export()
            })
        },
        dimsss() {
            //從原位向下移動dailog高度,形成從上向下的收起效果
            this.animation.translateY(this.data.dialogh).step()
            this.setData({
                animation: this.animation.export()
            })
            //動畫結束後蒙層消失
            setTimeout(() => {
                this.setData({
                    isShow: false
                })
            }, 300)
        },
        cancel() {
            this.triggerEvent("cancel")
            this.dimsss()
        },
        confirm() {
            this.triggerEvent("confirm", {
                selectDate: this.data.selectDate
            })
            this.dimsss()
        }
    }
})

元件的使用

想在父元件中使用封裝好的date-picker元件,先要在父元件的json檔案中宣告。

{
  "usingComponents": {
    "date-picker": "../../components/date-picker/date-picker"
  },
}

如果想實現簡單的選擇時間段並在頁面中顯示的功能,父元件程式碼如下編寫即可。
父元件wxml檔案:

<view class="option" bindtap="timeOpen" style="font-size: 16px;">
      {{selectDate}}
</view>
<date-picker id="picker" range="8" step="40" bindconfirm="confirm"></date-picker>

父元件js檔案:

Page({
    data: {
        selectDate: "",
        machineShow: false,
    },
    onLoad: function () {
        this.picker = this.selectComponent("#picker")
    },
    timeOpen() {
        this.picker.showDialog();
    },
    confirm(e) {
        this.setData({
            selectDate: e.detail.selectDate
        })
    },
})

2.結合vant weapp的date-picker

自定義定義的date-picker元件已經可以實現想實現的功能,但自定義的元件樣式不夠美觀。這時,我注意到了小程式可以使用vant的元件庫,元件庫多列選擇器的樣式可以自由修改,而且自帶樣式已經足夠美觀,所以下面考慮結合vant元件庫實現date-picker。

實現效果

具體實現

使用vant weapp的picker元件和popup元件可以更簡潔地實現想要的效果,打造自定義的date-picker元件。

首先需要在編寫元件的json檔案中匯入vant weapp的相應元件

{
    "component": true,
    "usingComponents": {
        "van-picker": "@vant/weapp/picker/index",
        "van-popup": "@vant/weapp/popup/index"
    }
}

然後編寫date-picker的wxml檔案:

<van-popup round show="{{ isShow }}" bind:close="cancel" position="bottom" custom-style="height: 55%">
  <van-picker show-toolbar columns="{{ date_time_list }}" bind:cancel="cancel" bind:change="change"
    bind:confirm="confirm" />
</van-popup>

因為van-picker的引數columns接受的是一個物件陣列,與picker-view有一定差異,所以需要將date-picker的js檔案進行如下更改。

1.修改data,增加date_time_list

data: {
        isShow: false,
        selectDate: "",
        dialogh: 0,

        //日期列表和時間列表
        date_list: [],
        time_list: [],
        date_time_list: []  //增加的欄位
    },

2.修改attached函數

//增加的內容
let date_time_list = [{
                values: date_list
            },
            {
                values: time_list  
            }
        ];
        this.setData({
            date_list: date_list,
            time_list: time_list,
            date_time_list: date_time_list  //增加的內容
        })

3.修改change函數

change: function (e) {
            let val = e.detail.value;
            let select = val[0] + val[1];
            this.setData({
                selectDate: select
            })

        },

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com