vue实现bar左右拖拽

效果图

功能

实现bar左右拖拽

左侧:js通过width控制 :style="{width: lwidth}"

右侧:盒子设置定位position,js通过的left来控制,同时样式需要设置 right: 0; bottom: 0; 才会出现width

中间:设置定位position,使用calc计算的时候,`calc(${this.left_width *100 }% - 5px)`,同时需要通过js来计算对应的位置设置left,:style="{left: bar_width}"

bar移动:

鼠标按下mousedown后监听鼠标移动mousemove和鼠标抬起mouseup事件;

在data中定义一个变量记录此时是抬起还是按下,按下可以移动,抬起不移动【鼠标移动和抬起都是给document绑定,因为在容器外也可以移动】;

出现的bug:不是点击正中间的bar时,bar会自动移动到中间,可以通过减去bar自身的宽度解决

扫描二维码关注公众号,回复: 11358572 查看本文章

解决办法:

data中定义一个【鼠标距离bar容器左侧的距离】initWidth,当鼠标按下时给这个值赋值,

this.initWidth = event.pageX - event.srcElement.getBoundingClientRect().left

在计算鼠标到大盒子box左侧距离时减去initWidth, 同时需要加上自身宽度的一半

let MBoffsetPrec = (event.pageX - this.$refs.wrapper.getBoundingClientRect().left - this.initWidth + 5)/this.$refs.wrapper.getBoundingClientRect().width

设置左右两侧的最大(盒子宽度 - bar一半宽度) 最小 (bar一半宽度) 临界值,不能超出边界外

const min = (this.$refs.bar.offsetWidth / 2) /this.$refs.wrapper.getBoundingClientRect().width
const max = (this.$refs.wrapper.getBoundingClientRect().width - (this.$refs.bar.offsetWidth / 2)) / this.$refs.wrapper.getBoundingClientRect().width

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .box{
      width: 500px;
      height: 300px;
      background-color: pink;
      position: relative;
      margin: 100px auto;
      overflow: hidden;
    }
    .left{
      position: absolute;
      top: 0;
      background-color: skyblue;
      /* width: 30%; */
      height: 100%;
    }
    .bar{
      position: absolute;
      height: 100%;
      width: 10px;
      background-color: teal;
      z-index: 2;
      user-select: none;
    }
    .right{
      position: absolute;
      top: 0;
      /* left: 30%; */
      right: 0;
      bottom: 0;
      background-color: yellow;
      height: 100%;
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="box" ref="wrapper">
      <div class="left" :style="{width: lwidth}" @click="handelChange">zuo</div>
      <div class="bar" :style="{left: bar_width}" @mousedown="handelMousedown" ref="bar"  @touchstart="handelTouch"></div>
      <div class="right" :style="{left: lwidth}">you</div>
    </div>
  </div>
  
  <script src="http://vuejs.org/js/vue.js"></script>
  <script>
    var vm=new Vue({
      el:'#app',
      data:{
        left_width: 0.5,
        // 记录鼠标按下还是抬起
        isMousemouse: false,
        //鼠标距离bar容器左侧的距离
        initWidth: 0 
      },
      methods:{
        handelChange(){
          this.left_width -= 0.05
          console.log(this.$refs.bar.offsetWidth / 2);
          
        },
        handelMousedown(event){
          this.isMousemouse = true

          this.initWidth = event.pageX - event.srcElement.getBoundingClientRect().left
          // console.log(this.initWidth);
          
          // 移动的时候给document绑定事件,在容器外也能移动
          document.addEventListener('mousemove',this.handelMousemove)
          // 在框外停下鼠标不能移动,也给document绑定事件
          document.addEventListener('mouseup',this.handelMouseup)
        },
        handelMousemove(event){
          if(this.isMousemouse){
            // event.pageX:鼠标指针相对于该网页的水平位置;getBoundingClientRect().left: 容器距离页面左侧距离
            // MBoffset: 鼠标距离盒子左侧的位置
            // initWidth:鼠标距离bar容器左侧的距离
            let MBoffsetPrec = (event.pageX - this.$refs.wrapper.getBoundingClientRect().left - this.initWidth + this.$refs.bar.offsetWidth / 2)/this.$refs.wrapper.getBoundingClientRect().width

            const min = (this.$refs.bar.offsetWidth / 2) /this.$refs.wrapper.getBoundingClientRect().width
            const max = (this.$refs.wrapper.getBoundingClientRect().width - (this.$refs.bar.offsetWidth / 2)) / this.$refs.wrapper.getBoundingClientRect().width

            if(MBoffsetPrec <  min){
              MBoffsetPrec = min
              return this.left_width = MBoffsetPrec

            }else if(MBoffsetPrec > max){
              return MBoffsetPrec = max
            }
            this.left_width = MBoffsetPrec
          }else{
            return
          }
        },
        handelMouseup(){
          this.isMousemouse = false
        },
        handelTouch(e){
          console.log('fjdkslfl')
        }
      },
      computed: {
        lwidth(){
          return (this.left_width * 100) + '%'
        },
        bar_width(){
          // 5 是bar的一半宽度
          return `calc(${this.left_width *100 }% - 5px)`
        }
      },
    })
  </script>
</body>
</html>

猜你喜欢

转载自www.cnblogs.com/yx1102/p/13170533.html