关于vue中鼠标拖拽元素的实现
大家好,我是敲代码时长两年半的很菜的🐔。关于vue中鼠标拖拽的实现,简单来说,就是绑定鼠标的按下,移动,松开事件,然后去变更坐标。实际实现起来也是每走一步都会遇到一个问题。请忽略代码中的拼写错误,不合规范等问题。
所以说为啥不去用插件呢
主要使用了vue.directive为组件设定一个唯一的key。因为页面可能会有多个可以拖拽的元素。这个时候就得为每个元素做出标识识别。还好js也有map。但是js的构造函数真的让我好找啊…最后靠vscode的代码补全试出来了。上代码吧。
首先是比较普通的vue页面。用了个自定义的指令,方便之后的操作。
<template>
<div>
<div v-drag="'box1'" class="defaultBox">1</div>
<div v-drag="'box2'" class="defaultBox">2</div>
<div v-drag="'box3'" class="defaultBox">3</div>
<div v-drag="'box4'" class="defaultBox">4</div>
<div v-drag="'box|1'" class="hiBox">5</div>
<div v-drag="'box|2'" class="hiBox">6</div>
<div v-drag="'box|3'" class="hiBox">7</div>
<div v-drag="'box|4'" class="hiBox">8</div>
<div v-drag="'box-1'" class="wiBox">9</div>
<div v-drag="'Box'" class="bigBox">10</div>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.defaultBox{
width: 100px;
height: 100px;
border: 1px red solid;
}
.hiBox{
width: 100px;
height: 200px;
border: 1px red solid;
}
.wiBox{
width: 200px;
height: 100px;
border: 1px red solid;
}
.bigBox{
width: 200px;
height: 200px;
border: 1px red solid;
}
</style>
基本上很正常。我觉得没写过vue的都看懂了。
然后就是需要脑子去写的js代码了。这里参考了这篇文章
康一康
export const allowDrag = (vue) => {
vue.directive('drag', {
bind: (el, binding) => respMouse(el, binding),
update: (el, binding) => respMouse(el, binding),
inserted: (el, binding) => respMouse(el, binding),
})
}
let drapMap = new Map();
// 构造函数,存储元素与坐标
class DrapElement {
constructor(element, key) {
this.element = element;
this.borderX = 0;
this.borderY = 0;
this.moveable = false;
this.key = key;
this.element.onmousedown = (e) => savePosition(e, this.key);
this.element.onmousemove = (e) => moveElement(e, this.key);
this.element.onmouseup = (e) => newPosition(e, this.key);
}
}
const respMouse = (el, binding) => {
if (!drapMap.has(binding.value)) {
let dragEL = new DrapElement(el, binding.value);
dragEL.element = el;
dragEL.element.style.zIndex = 100;
dragEL.element.style.position = 'fixed';
drapMap.set(binding.value, dragEL)
}
}
// 鼠标按下事件
const savePosition = (e, key) => {
let drapElement = drapMap.get(key)
drapElement.borderX = e.clientX - drapElement.element.offsetLeft;
drapElement.borderY = e.clientY - drapElement.element.offsetTop;
drapElement.moveable = true;
drapElement.element.style.cursor = 'grabbing'
drapElement.element.style.zIndex = 1000;
}
// 鼠标移动事件
const moveElement = (e, key) => {
let drapElement = drapMap.get(key)
if (!drapElement.moveable)
return;
let ofsX = e.clientX - drapElement.borderX;
let ofsY = e.clientY - drapElement.borderY;
drapElement.element.style.cursor = 'grabbing'
drapElement.element.style.left = `${ofsX}px`;
drapElement.element.style.top = `${ofsY}px`;
drapElement.element.style.zIndex = 1000;
}
// 鼠标松开事件
const newPosition = (e, key) => {
let drapElement = drapMap.get(key)
drapElement.moveable = false;
drapElement.element.style.cursor = 'grab'
drapElement.element.style.zIndex = 100;
}
这里更改zIndex主要是为了保证拖拽的时候不会因为经过其他元素而被拦住。
之后只要在main.js加上
import { allowDrag } from './js/config/drag/index.js'
allowDrag(Vue);
这里看自己的实际的文件位置之类的去改。
好了。可以运行一下看看实际效果了(玩过华容道的可以动手试试了)