vue实现滑块slider(赋源码)

因为项目用到滑块,只要一处使用到看了第三方库觉得没必要引入导致项目太臃肿:
先上代码:

<template>
    <div class="slider" ref="mySlider">
        <div class="left-btn" :class="{active:myPosition.isBtn==2}"></div>
        <div class="propo"></div>
        <div class="propo-bg"></div>
        <div class="right-btn" :class="{active:myPosition.isBtn==1}"></div>
    </div>
</template>
<script type="text/javascript">
    export default {
        name: 'slider',
        props:{
            "valueFun":{
                type:Function,
                required: true,
            },
            "max":{
                type:Number,
                default:100
            },
            "min":{
                type:Number,
                default:0
            }
        },
        data(){
            return{
                myPosition:{
                    left:0,
                    right:0,
                    now:0,
                    isBtn:0,
                    propoWidth:0
                },
                myDefault:null
            }
        },
        methods:{

        },
        mounted(){
            //滑块
            let that = this
            let mySlider = this.$refs.mySlider
            let propo = mySlider.children[1]
            let rightBtn = mySlider.children[3]
            let leftBtn = mySlider.children[0]
            let myWidth = 0

            const elementLeft = (e) => { //计算x坐标
                var offset = e.offsetLeft;
                if(e.offsetParent != null) offset += elementLeft(e.offsetParent);
                return offset;
            }

            const myCount = () => { //计算滑动
                if(this.myPosition.right>this.myPosition.left){ //判断滑动范围
                    this.myPosition.propoWidth = this.myPosition.right - this.myPosition.left
                    propo.style.width = this.myPosition.propoWidth+'%'
                    propo.style.left = this.myPosition.left + '%'
                    this.valueFun(parseInt(this.myPosition.left),parseInt(this.myPosition.right),parseInt(this.myPosition.propoWidth))
                }else if(this.myPosition.right<this.myPosition.left){
                    this.myPosition.propoWidth = this.myPosition.left - this.myPosition.right
                    propo.style.width = this.myPosition.propoWidth+'%'
                    propo.style.left = this.myPosition.right+'%'
                    this.valueFun(parseInt(this.myPosition.right),parseInt(this.myPosition.left),parseInt(this.myPosition.propoWidth))
                }
            }

            this.myDefault = () => {//初始化
                this.myPosition.right = this.max
                this.myPosition.left = this.min

                if(this.max > this.min){
                    this.myPosition.propoWidth = this.max - this.min
                    propo.style.left = this.myPosition.left + '%'
                }else{
                    this.myPosition.propoWidth = this.min - this.max
                    propo.style.left = this.myPosition.right + '%'
                }

                propo.style.width = this.myPosition.propoWidth+'%'
                leftBtn.style.left = this.myPosition.right + '%'
                rightBtn.style.left = this.myPosition.left + '%'
                this.valueFun(this.myPosition.left,this.myPosition.right,this.myPosition.propoWidth)
            }

            let mySliderX = elementLeft(mySlider) //滑动块x坐标

            mySlider.addEventListener('touchmove',(e)=>{ //屏幕滑动事件
                let pageX = e.touches[0].pageX-mySliderX //获取滑动x坐标
                myWidth = (pageX/mySlider.offsetWidth)*100 //计算百分比
                if(myWidth>100){ //判断不超出范围
                    myWidth=100
                }else if(myWidth<0){
                    myWidth=0
                }

                if(this.myPosition.isBtn == 1){//判断焦点
                    this.myPosition.left = myWidth
                    rightBtn.style.left = myWidth+'%' 
                }else if(this.myPosition.isBtn == 2){
                    this.myPosition.right = myWidth
                    leftBtn.style.left = myWidth+'%' 
                }

                myCount()
                e.preventDefault()

            })

            mySlider.addEventListener('touchstart',(e)=>{//屏幕触摸事件
                let touchX = e.touches[0].pageX-mySliderX
                let btnWidth = (leftBtn.offsetWidth/mySlider.offsetWidth)/2*100 //计算按钮宽度
                this.myPosition.now = (touchX/mySlider.offsetWidth)*100
                mySliderX = elementLeft(mySlider) //滑动块x坐标
                if(this.myPosition.now <= this.myPosition.left+btnWidth&&this.myPosition.now >= this.myPosition.left-btnWidth){ //计算区间 获取焦点
                    this.myPosition.isBtn = 1
                }else if(this.myPosition.now <= this.myPosition.right+btnWidth&&this.myPosition.now >= this.myPosition.right-btnWidth){
                    this.myPosition.isBtn = 2
                }else{
                    this.myPosition.isBtn = 0
                }
            })

            this.myDefault()
        },
        watch:{
            min(New,old){
                this.myDefault()
            },
            max(New,old){
                this.myDefault()
            }
        }
    }
</script>
<style lang="scss">
    .slider{
            width: 100%;
            position:relative;
            height: 0.5rem;
            .left-btn,.right-btn{
                position: absolute;
                top: -0.34rem;
                transform:translate(-50%,0);
                &:before{
                    content: ""; 
                    display: block;
                    width: 0; 
                    height: 0.4rem;
                    border-left: 0.17rem solid transparent; 
                    border-right: 0.17rem solid transparent; 
                    border-bottom: 0.17rem solid #B6B6B6; 
                }
                &:after{
                    content: "";
                    display: block;
                    height: 0.30rem;
                    width: 0.34rem;
                    background: #B6B6B6;
                    border-bottom-left-radius: 0.1rem;
                    border-bottom-right-radius: 0.1rem;
                }
            }
            .propo{
                width: 0%;
                height: 0.04rem;
                background: #FFD00D;
                position: absolute;
                top: 0;
                left: 0;
                z-index: 2;
            }
            .propo-bg{
                background: #B6B6B6;
                border-radius: 0.04rem;
                height: 0.04rem;
                width:100%;
                position: absolute;
                top: 0;
                left: 0;
                z-index: 1;
            }
            .active{
                &:before{
                    border-bottom-color: #FF8C30
                }
                &:after{
                    background: #FF8C30;
                }
            }
    }
</style>

实现思路:
首先通过$refs获取dom节点
通过touchstart事件获取触摸的x坐标 判断按钮焦点
通过touchmove判断之前的焦点并获取滑动距离
然后计算滑动距离(滑动的x坐标减掉最父级节点的x坐标,注:最父级节点是动态改变的 所以得动态获取)

调用方法:

<slider :value-fun="Val" :min="0" :max="100"></slider>

样式:

github : https://github.com/474782977/vue-slider

  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值