关于vue中鼠标拖拽元素的实现

关于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);

这里看自己的实际的文件位置之类的去改。
好了。可以运行一下看看实际效果了(玩过华容道的可以动手试试了)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue可以通过绑定mousedown、mousemove、mouseup事件来实现拖拽边框改变元素宽度。具体步骤如下: 1. 绑定mousedown事件,在事件处理函数记录鼠标点击的初始位置和被拖拽元素的初始宽度。 2. 绑定mousemove事件,在事件处理函数计算鼠标的相对移动距离,并根据鼠标移动距离更新被拖拽元素的宽度。 3. 绑定mouseup事件,在事件处理函数取消mousemove和mouseup事件的绑定。 下面是示例代码: ``` <template> <div class="drag-wrapper"> <div class="drag-target" :style="{ width: targetWidth + 'px' }"> Drag Me </div> <div class="drag-handle" @mousedown="handleDown"></div> </div> </template> <script> export default { data () { return { isDragging: false, startX: 0, startWidth: 0, targetWidth: 200 } }, methods: { handleDown (e) { this.isDragging = true this.startX = e.clientX this.startWidth = this.targetWidth document.addEventListener('mousemove', this.handleMove) document.addEventListener('mouseup', this.handleUp) }, handleMove (e) { if (!this.isDragging) return const deltaX = e.clientX - this.startX this.targetWidth = this.startWidth + deltaX }, handleUp () { this.isDragging = false document.removeEventListener('mousemove', this.handleMove) document.removeEventListener('mouseup', this.handleUp) } } } </script> <style scoped> .drag-wrapper { position: relative; height: 100px; padding: 10px; background-color: #ddd; } .drag-target { height: 100%; background-color: #fff; text-align: center; line-height: 80px; font-size: 20px; border: 1px solid #333; } .drag-handle { position: absolute; top: 0; right: -5px; bottom: 0; width: 10px; background-color: #333; cursor: ew-resize; } </style> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值