【微信原生小程序】手写双向slider滑块

前言

官方自带的以及vant weapp组件都是只有单向的slider
在这里插入图片描述

双向的slider,网上抄了几篇文章,代码量巨大而且还有各种bug,相当难用,chatGPT写的也没法用,没办法,只能自己手写一个了

在这里插入图片描述

实现了的几个细节(别的文章里大部分存在这些bug)

一、当左滑块拖动的范围超过父容器最左边时,赋值为0;
右边同理赋值为最大值
二、当右滑块向左滑,并且试图越过左滑块时,右边赋值与左边相等,并且无法越过左边(最多就是两个圆圈紧挨着)
三、可重置

父组件代码(很简单)

<my-slider bind:submit="getAge" ></my-slider>
getAge(e){
    this.setData({
         min: e.detail.min,
         max: e.detail.max,
     })
 }

子组件代码(最重要的部分)

<view class="slider-background">
  <view class="slider" style="padding-left: {{pdLeft}}rpx;padding-right: {{pdRight}}rpx;">
    <view class="slider-circle" bindtouchstart="touchStart1" bindtouchmove="touchMove1" bindtouchend="touchEnd1"></view>
    <view class="main-slider"></view>
    <view class="slider-circle" bindtouchstart="touchStart2" bindtouchmove="touchMove2" bindtouchend="touchEnd2"></view>
  </view>
</view>

.slider-background{
  width: 684rpx;
  margin: 0 auto;
  display: flex;
  align-items: center;
  height: 8rpx;
  background-color: rgb(228, 228, 228);
}
.slider{
  width: 100%;
  padding: 0;
  display: flex;
  align-items: center;
}
.slider .main-slider{
  width: calc(100% - 84rpx);
  height: 8rpx;
  background-color: blue;
}
.slider .slider-circle{
  width:  42rpx;
  height: 42rpx;
  background-color: #fff;
  border-radius: 50%;
  box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.5);

}
// components/slider/index.js
Component({
    // 使用全局样式
    options: {
        addGlobalClass: true
    },
    lifetimes: {
        attached: function() {
          // 在组件实例进入页面节点树时执行
            const res = wx.getSystemInfoSync()
            this.setData({
                ratio: 750 / res.windowWidth
            })
          
        },
        detached: function() {
          // 在组件实例被从页面节点树移除时执行
        },
    },
    /**
     * 组件的属性列表
     */
    properties: {

    },

    /**
     * 组件的初始数据
     */
    data: {
        pdLeft: 0,     // 左边滑块的位置
        pdRight: 0,     // 右边滑块的位置
        ratio: 2,
        startX1: 0,     //计算左滑块初始位置离屏幕左边的距离
        startX2: 0,     //计算右滑块初始位置离屏幕右边的距离
    },

    /**
     * 组件的方法列表
     */
    methods: {
        touchStart1(e){
            // console.log("e0", e.touches[0].clientX);
            if(!this.data.startX1){
                this.setData({
                    startX1: e.touches[0].clientX
                })

            }
        },
        touchMove1(e){
            // console.log("eeee1", e.touches[0].clientX);
            let x = (e.touches[0].clientX - this.data.startX1) * this.data.ratio
            let v = x >= 0 ? x : 0               //不能超过父容器最左边
            if(v + this.data.pdRight >= 600){    //右边的滑块越过左边时
                v = 600 - this.data.pdRight
            }
            this.setData({
                pdLeft: v
            })
            this.triggerEvent('submit', {
                min: Math.round(v/5),
            })
            // console.log("this.data.pdLeft", this.data.pdLeft);
        },
        touchEnd1(){},
        touchStart2(e){
            // console.log("e0", e.touches[0].clientX);
            if(!this.data.startX2){
                this.setData({
                    startX2: e.touches[0].clientX
                })

            }
        },
        touchMove2(e){
            // console.log("eeee2", e.touches[0].clientX);
            let x = (this.data.startX2 - e.touches[0].clientX) * this.data.ratio
            let v = x >= 0 ? x : 0              //不能超过父容器最右边
            if(v + this.data.pdLeft >= 600){    //右边的滑块越过左边时
                v = 600 - this.data.pdLeft
            }
            this.setData({
                pdRight: v
            })
            this.triggerEvent('submit', {
                max: Math.round((600-v)/5),
            })
            // console.log("this.data.pdRight", this.data.pdRight);
        },
        touchEnd2(){},
        reset(){
            this.setData({
                pdLeft: 0,
                pdRight: 0,
                startX1: 0,
                startX2: 0,
            })
            this.triggerEvent('submit', {
                min: 0,
                max: 120
            })
        },
        
    }
})

备注

看js文件可以看到,我是直接在里面写了0到120,如果要设计成最小值最大值从父组件传进来可以自己稍作修改。
其他参数同理(颜色,圆圈样式等等)

存在的问题

父容器写死了width: 684rpx;减去两个圆圈刚好是600rpx;所以js里很多计算都是直接用600进行计算。

优化方案:可以改成父容器里写width: 100%;然后在js里先调用方法来获取他的宽度

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现微信小程序双向滑块slider,可以使用小程序官方提供的组件`<slider>`,并结合自定义组件和数据绑定来实现。 具体实现步骤如下: 1. 在小程序页面中引入`<slider>`组件,设置min、max、step、value等属性,如下: ```html <slider min="0" max="100" step="1" value="{{sliderValue}}" bindchange="onSliderChange"></slider> ``` 其中,`sliderValue`为双向滑块的值,`onSliderChange`为滑动时的回调函数。 2. 创建自定义组件`<double-slider>`,包含两个`<slider>`组件,分别用于设置起始值和结束值,如下: ```html <view class="double-slider"> <slider min="0" max="{{maxValue}}" step="{{step}}" value="{{startValue}}" bindchange="onStartChange"></slider> <slider min="{{startValue}}" max="{{maxValue}}" step="{{step}}" value="{{endValue}}" bindchange="onEndChange"></slider> </view> ``` 其中,`maxValue`为最大值,`step`为步长,`startValue`为起始值,`endValue`为结束值,`onStartChange`和`onEndChange`分别为起始值和结束值滑动时的回调函数。 3. 在页面中引入自定义组件`<double-slider>`,并设置相应的属性和绑定数据,如下: ```html <double-slider maxValue="100" step="1" startValue="{{startValue}}" endValue="{{endValue}}" onStartChange="onSliderChange" onEndChange="onSliderChange"></double-slider> ``` 其中,`maxValue`和`step`为自定义组件的属性,`startValue`和`endValue`为双向滑块的值,`onStartChange`和`onEndChange`为双向滑块滑动时的回调函数。 4. 在页面的js文件中,定义相应的函数来处理滑块滑动时的操作,如下: ```javascript Page({ data: { startValue: 0, endValue: 100 }, onSliderChange: function (e) { let value = e.detail.value; this.setData({ startValue: value[0], endValue: value[1] }); }, onStartChange: function (e) { let value = e.detail.value; this.setData({ startValue: value }); }, onEndChange: function (e) { let value = e.detail.value; this.setData({ endValue: value }); } }) ``` 其中,`onSliderChange`函数处理双向滑块滑动时的操作,将起始值和结束值保存在`startValue`和`endValue`中;`onStartChange`函数处理起始值滑动时的操作,将起始值保存在`startValue`中;`onEndChange`函数处理结束值滑动时的操作,将结束值保存在`endValue`中。 这样,就可以实现微信小程序双向滑块slider了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值