vue实现拖拽组件
可以拖拽,靠边停靠,效果图如下
![](https://img2018.cnblogs.com/i-beta/1259550/201912/1259550-20191229101039321-1884936401.png)
代码如下: 注意:代码中使用的图片未上传 DragAndDrop组件: <template> <div class="drag" id="moveDiv" @mousedown="start($event)" @touchstart="start($event)" @mousemove="move($event)" @touchmove="move($event)" @mouseup="end($event)" @touchend="end($event)"> <slot name="drag-cont"></slot> <div id="optionBall"></div> <div id="optionContent" v-show="optionContentShow"> <span class="imgWrap" @click="gatewayOption" v-bind:style="{backgroundColor : this.$parent.whichOption? '#ff5b45' : '#ffffff'}" > <img v-bind:src="this.$parent.whichOption?require('../assets/img/SmartGateway_write.png'):require('../assets/img/SmartGateway.png')" alt="" width="24px" height="24px"> </span> <span class="imgWrap" @click="alertOption" v-bind:style="{backgroundColor : !this.$parent.whichOption? '#ff5b45' : '#ffffff'}"> <img v-bind:src="!this.$parent.whichOption?require('../assets/img/alert_write.png'):require('../assets/img/alert.png')" alt="" width="24px" height="24px"> </span> </div> </div><!--E 拖动组件 --> </template> <script> export default { name: "dragAndDrop", data() { return { position: {x: 0,y: 0}, // 鼠标点击的x轴和y轴的距离 nx: '', // 鼠标当前距离元素的左侧距离 ny: '', // 鼠标当前距离元素的顶部距离 dx: '', // 元素距离左侧的距离 dy: '', // 元素距离顶部的距离 xPum: '', // 元素移动的x轴距离 yPum: '', // 元素移动的y轴距离 optionContentShow: true }; }, methods: { start(e){ // 如果touches存在就说明是移动端 // 否则为pc端直接获取事件源对象 let touch = e.touches? e.touches[0] : e; this.position.x = touch.clientX; this.position.y = touch.clientY; this.dx = moveDiv.offsetLeft; this.dy = moveDiv.offsetTop; this.optionContentShow = true; }, move(e){ this.isDrop = true; if(this.isDrop){ let touch = e.touches? e.touches[0] : e; this.nx = touch.clientX - this.position.x; this.ny = touch.clientY - this.position.y; this.xPum = this.dx+this.nx; this.yPum = this.dy+this.ny; moveDiv.style.left = this.xPum + "px"; moveDiv.style.top = this.yPum + "px"; document.addEventListener("touchmove",function(){ event.preventDefault(); },false); if(e.preventDefault){ e.preventDefault(); }else{ window.event.returnValue == false; } } }, end(e){ let oWidth = moveDiv.offsetWidth; // Element Width let oWrapWidth = moveDiv.parentNode.offsetWidth; // Parent Element Width let oWrprapHeight = moveDiv.parentNode.offsetHeight; // Parent Element Height let sumWidth = moveDiv.offsetLeft + oWidth; // Element Left + Element Width let sumHeight = moveDiv.offsetTop + moveDiv.offsetHeight; // Element Top + Element Height // The Limit Deal if(moveDiv.offsetLeft < 0) { moveDiv.style.left = 0; this.optionContentShow = false; moveDiv.style.left = "-30px"; } else if(sumWidth > oWrapWidth){ moveDiv.style.left = oWrapWidth - oWidth + 'px'; // console.log("到最右边了"); this.optionContentShow = false; moveDiv.style.left = "-30px"; } else if(moveDiv.offsetTop < 0) { moveDiv.style.top = 0; } else if(sumHeight > oWrprapHeight) { moveDiv.style.top = oWrprapHeight - moveDiv.offsetHeight + 'px'; } document.onmousemove = null; document.onmouseup = null; }, gatewayOption: function () { this.$parent.gatewayOption(); }, alertOption: function () { this.$parent.alertOption(); }, } }; </script> <style scoped> .drag { width: 160px; height: 60px; position: absolute; left: 40px; bottom: 60px; z-index: 999; } #optionBall { width: 56px; height: 56px; position: absolute; background-color: #ff5b45; border-radius: 56px; z-index: 20; } #optionContent { width: 130px; height: 50px; background-color: #ff956b; position: absolute; left: 20px; margin-top: 3px; border-radius: 50px; z-index: 10; padding: 6px 0 6px 34px; box-sizing: border-box; } .imgWrap { display: inline-block; width: 38px; height: 38px; background-color: #ffffff; border-radius: 40px; padding: 8px; box-sizing: border-box; } .checked { background-color: #ff5b45; } </style> 父组件:subDevice.vue <template> <DragAndDrop></DragAndDrop> </template> <script> import DragAndDrop from "./DragAndDrop"; export default { name: "subDevice", components: {DragAndDrop,InfiniteScroll}, data() { return { whichOption: true } }, methods:{ gatewayOption: function () { this.whichOption = true; }, alertOption: function () { this.whichOption = false; } } } </script>
路漫漫其修远兮,吾将上下而求索