基于Vue实现元素拖拽效果

在实现拖拽效果时需要先理解clientY pageY screenY layerY offsetY的区别
clientY 指的是距离可视页面左上角的距离
pageY 指的是距离可视页面左上角的距离(不受页面滚动影响)
screenY 指的是距离屏幕左上角的距离
layerY 指的是找到它或它父级元素中最近具有定位的左上角距离
offsetY 指的是距离它自己左上角的距离
思路
onmousedown:鼠标按下事件
onmousemove:鼠标移动事件
onmouseup:鼠标抬起事件
拖拽的基本原理就是根据鼠标的移动来移动被拖拽的元素。鼠标的移动也就是x、y坐标的变化;元素的移动就是style.position的 top和left的改变。当然,并不是任何时候移动鼠标都要造成元素的移动,而应该判断鼠标左键的状态是否为按下状态,是否是在可拖拽的元素上按下

拖拽状态 = 鼠标在元素上按下的时候{      
    记录下鼠标的x和y坐标      
    记录下元素的x和y坐标      
   }   
鼠标在元素上移动的时候{      
    元素y = 现在鼠标y - 原来鼠标y + 原来元素y      
    元素x = 现在鼠标x - 原来鼠标x + 原来元素x      
    }      
鼠标在任何时候放开的时候{      
   鼠标弹起来的时候不再移动      
} 

直接上代码,代码中有注释

<template>
    <div class="drag">
        <div class="drag_box" v-drag></div>
    </div>
</template>

<script>
export default {
    name: "drag",
    data() {
        return {};
    },
    //注册局部组件指令
    directives: {
        drag: function(el) {
            let dragBox = el; //获取当前元素
            dragBox.onmousedown = e => {
                //算出鼠标相对元素的位置
                let disX = e.clientX - dragBox.offsetLeft;
                let disY = e.clientY - dragBox.offsetTop;
                document.onmousemove = e => {
                    //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
                    let left = e.clientX - disX;
                    let top = e.clientY - disY;
                    //移动当前元素
                    dragBox.style.left = left + "px";
                    dragBox.style.top = top + "px";
                };
                document.onmouseup = e => {
                      //鼠标弹起来的时候不再移动
                      document.onmousemove = null;
                     //预防鼠标弹起来后还会循环(即预防鼠标放上去的时候还会移动)  
                    document.onmouseup = null;
                };
            };
        }
    }
};
</script>
<style scoped>
.drag {
    width: 100%;
    height: 500px;
    background-color: #fff;
}
.drag_box {
    width: 150px;
    height: 90px;
    border: 1px solid #666;
    background-color: #ccc;
    /* 使用定位,脱离文档流 */
    position: relative;
    top: 100px;
    left: 100px;
    /* 鼠标移入变成拖拽手势 */
    cursor: move;
    z-index: 3000;
}
</style>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
推荐使用 Element Plus + Vue.js,可以结合使用拖拽库如 vue-draggable-resizable 和 vue-grid-layout。 Element Plus 是一款基于 Vue.js 2.0 的 UI 组件库,提供了丰富的组件和功能。而 vue-draggable-resizable 是一款基于 Vue.js 的可拖拽和可调整大小的组件库,可以快速实现拖拽和调整元素大小的功能。vue-grid-layout 则是一个响应式的网格布局系统,可以帮助我们更好地管理和布局页面元素。 具体实现步骤如下: 1. 首先安装 Element Plus 和 vue-draggable-resizable。 ```bash npm install element-plus vue-draggable-resizable ``` 2. 引入 Element Plus 和 vue-draggable-resizable。 ```javascript import ElementPlus from 'element-plus'; import 'element-plus/lib/theme-chalk/index.css'; import VueDraggableResizable from 'vue-draggable-resizable'; import 'vue-draggable-resizable/dist/VueDraggableResizable.css'; ``` 3. 注册 Element Plus 组件和 vue-draggable-resizable 组件。 ```javascript Vue.use(ElementPlus); Vue.component('vue-draggable-resizable', VueDraggableResizable); ``` 4. 创建一个页面布局组件,使用 vue-draggable-resizable 实现元素拖拽和调整大小。 ```html <template> <div class="page-layout"> <vue-draggable-resizable v-for="(item, index) in items" :key="index" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :min-w="item.minW" :min-h="item.minH" :max-w="item.maxW" :max-h="item.maxH" :z="item.z" :isDraggable="item.isDraggable" :isResizable="item.isResizable" :onDragStart="onDragStart" :onDrag="onDrag" :onDragStop="onDragStop" :onResizeStart="onResizeStart" :onResize="onResize" :onResizeStop="onResizeStop" > <div class="inner">{{ item.content }}</div> </vue-draggable-resizable> </div> </template> <script> export default { data() { return { items: [ { x: 0, y: 0, w: 2, h: 2, minW: 1, minH: 1, maxW: 6, maxH: 6, z: 1, isDraggable: true, isResizable: true, content: 'Element 1', }, { x: 2, y: 0, w: 2, h: 4, minW: 1, minH: 1, maxW: 6, maxH: 6, z: 2, isDraggable: true, isResizable: true, content: 'Element 2', }, // ... ], }; }, methods: { onDragStart(event, ui) { console.log('onDragStart', event, ui); }, onDrag(event, ui) { console.log('onDrag', event, ui); }, onDragStop(event, ui) { console.log('onDragStop', event, ui); }, onResizeStart(event, ui) { console.log('onResizeStart', event, ui); }, onResize(event, ui) { console.log('onResize', event, ui); }, onResizeStop(event, ui) { console.log('onResizeStop', event, ui); }, }, }; </script> <style scoped> .page-layout { position: relative; height: 500px; border: 1px solid #ccc; } .inner { height: 100%; display: flex; align-items: center; justify-content: center; } </style> ``` 5. 使用 vue-grid-layout 实现响应式布局。 ```html <template> <div class="page-layout"> <vue-grid-layout :layout="layout" :rowHeight="30" :cols="12" :isDraggable="true" :isResizable="true" :verticalCompact="false" :margin="[10, 10]" @layout-update="onLayoutUpdate" > <div v-for="(item, index) in items" :key="index" :data-grid="{x: item.x, y: item.y, w: item.w, h: item.h, i: item.i}" > <div class="inner">{{ item.content }}</div> </div> </vue-grid-layout> </div> </template> <script> import VueGridLayout from 'vue-grid-layout'; export default { data() { return { layout: [ { x: 0, y: 0, w: 2, h: 2, i: '1' }, { x: 2, y: 0, w: 2, h: 4, i: '2' }, // ... ], items: [ { x: 0, y: 0, w: 2, h: 2, content: 'Element 1', }, { x: 2, y: 0, w: 2, h: 4, content: 'Element 2', }, // ... ], }; }, components: { VueGridLayout, }, methods: { onLayoutUpdate(layout) { this.layout = layout; this.items = layout.map((item) => { const { x, y, w, h } = item; const index = parseInt(item.i) - 1; return { x, y, w, h, content: `Element ${index + 1}`, }; }); }, }, }; </script> <style scoped> .page-layout { position: relative; height: 500px; border: 1px solid #ccc; } .inner { height: 100%; display: flex; align-items: center; justify-content: center; } </style> ``` 以上是基于 vue 的可视化拖拽页面生成工具的实现方法,可以根据自己的需求进行选择和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值