zoukankan      html  css  js  c++  java
  • vue实现bar左右拖拽

    效果图

    功能

    实现bar左右拖拽

    左侧:js通过width控制 :style="{ 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;
          /*  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="{ 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_ 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>
  • 相关阅读:
    获取网页源代码
    python下载图片
    vue框架前后端分离项目之登录注册页面及多方式登录、手机号验证码接口等相关内容-121
    django框架前后端混合项目之表设计、数据库及form组件等相关内容-77
    vue框架前后端分离项目之git分支合并及首页登陆注册接口等相关内容-120
    vue框架前后端分离项目之git的使用等相关内容-119
    vue框架前后端分离项目之xadmin、轮播图接口及git的介绍等相关内容-118
    vue框架前后端分离项目之跨域问题及首页搭建等相关内容-117
    vue框架前后端分离项目之框架介绍及前后端配置等相关内容-116
    django框架之自定义中间件及csrf跨站请求伪造等相关内容-75
  • 原文地址:https://www.cnblogs.com/yx1102/p/13170533.html
Copyright © 2011-2022 走看看