最终效果
完整代码
关键性要点,详见注释
组件封装 superBox.vue
<template> <div ref="box_Ref" class="box" @mousedown="moveStart" @mousemove="moving" @mouseup="moveEnd" :style="{ width: (nodeInfo.width || 40) + 'px', height: (nodeInfo.height || 60) + 'px', left: (nodeInfo.x || 0) + 'px', top: (nodeInfo.y || 0) + 'px', backgroundColor: nodeInfo.color || 'black', zIndex: zIndex, }" ></div> </template> <script> export default { props: { nodeInfo: Object, }, data() { return { zIndex: "auto", // 移动开始时,鼠标的x坐标 moveStart_mouseX: null, // 移动开始时,鼠标的y坐标 moveStart_mouseY: null, ifMove: false, originNodeInfo: null, }; }, methods: { // 移动开始 moveStart(e) { this.moveStart_mouseX = e.clientX; this.moveStart_mouseY = e.clientY; this.ifMove = true; this.originNodeInfo = JSON.parse(JSON.stringify(this.nodeInfo)); // 移动时,临时提升元素至顶层,避免因元素遮挡而无法继续移动 this.zIndex = 99999; }, // 移动中 moving(e) { if (this.ifMove) { let moveing_mouseX = e.clientX; let moveing_mouseY = e.clientY; let xChange = moveing_mouseX - this.moveStart_mouseX; let yChange = moveing_mouseY - this.moveStart_mouseY; this.$emit("moved", { newX: this.originNodeInfo.x + xChange, newY: this.originNodeInfo.y + yChange, }); } }, // 移动结束 moveEnd() { this.ifMove = false; this.moveStart_mouseX = null; this.moveStart_mouseY = null; this.originNodeInfo = null; this.zIndex = "auto"; }, }, }; </script> <style scoped> .box { position: absolute; cursor: move; } </style>
使用组件 index.vue
<template> <div> <SuperBox @moved="moved($event, node1)" :nodeInfo="node1" /> <SuperBox @moved="moved($event, node2)" :nodeInfo="node2" /> </div> </template> <script> import SuperBox from "./superBox.vue"; export default { components: { SuperBox, }, data() { return { node1: { x: 100, y: 10, color: "red", }, node2: { x: 400, y: 10, color: "blue", }, }; }, methods: { moved(movedInfo, nodeInfo) { // < 0 时置为0,避免元素移出浏览器窗口 nodeInfo.x = movedInfo.newX < 0 ? 0 : movedInfo.newX; nodeInfo.y = movedInfo.newY < 0 ? 0 : movedInfo.newY; }, }, }; </script>
遗留问题
当鼠标拖拽过快时,元素无法跟随移动,且 ifMove 无法正常恢复 false 导致拖拽异常。
想到解决方案的朋友,欢迎留言哦!
更多相关参考资料
- vue实战——元素的拖拽 + 控制元素无法拖拽出盒子 + 随元素拖拽自适应变化大小的盒子
https://blog.csdn.net/weixin_41192489/article/details/120518561