效果图
功能
实现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>