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自身的寬度解決

解決辦法:

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"></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
        }
      },
      computed: {
        lwidth(){
          return (this.left_width * 100) + '%'
        },
        bar_width(){
          // 5 是bar的一半寬度
          return `calc(${this.left_width *100 }% - 5px)`
        }
      },
    })
  </script>
</body>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM