Vue拖拽组件
vue开发公众号项目,***产品需要添加一个新的功能。拖拽功能。一听简单。百度上轮子挺多,直接拉一个过来用着就行。然鹅。。。兴奋之余,却失望至极。东西很多,没有一个能使得。你让我失望,那我就让你绝望。于是,拖拽的故事就开始了。。
vue拖拽功能
必备知识点:
先给不懂的童鞋补充下流程,文章要细读方能拖动元素到你心里~
按下的时候,我们需要获取
元素当前的 具有相对定位元素的左侧距离
元素当前的具有相对定位元素的顶部距离
鼠标按下点的x轴距离(鼠标左侧的距离)
鼠标按下点的y轴距离 (鼠标顶部的距离)
获取到这些点,先存储起来,后面的计算需要用到这些值
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;
}
Step1.
让元素跟着鼠标的移动不断移动。既然鼠标的x轴和y轴可以获取到,那我们就可以通过计算来让元素实现移动。
移动的时候,我们需要获取并设置
鼠标此时的当前的x轴和y轴的距离
鼠标点击的x轴和y轴的距离(按下的时候定义过)
此时用移动的距离 - 点击的起始位置就是移动的距离。
赋值给点击元素的left和top即可。
补充:计算的方式很多种,这知识其中一种
move(e){
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";
},
Step2.
离开的时候,我们需要抬起和移动事件从栈中清除掉,并且在结束时对边界做一个处理。不让元素拖动到屏幕外面,否则的话,不小心拖出去了,拉都拉不回来。这就很尴尬了。
元素的宽度
父元素的宽度和高度
元素的左侧距离 + 元素的宽度
元素的顶部距离 + 元素的高度
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;
} else if(sumWidth > oWrapWidth){
moveDiv.style.left = oWrapWidth - oWidth + 'px';
} 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;
}
组件源码
考虑到复用性,pc和移动端。
<template>
<!--S 拖动组件 -->
<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><!--E 拖动组件 -->
</template>
<script>
export default {
data() {
return {
position: {x: 0,y: 0}, // 鼠标点击的x轴和y轴的距离
nx: '', // 鼠标当前距离元素的左侧距离
ny: '', // 鼠标当前距离元素的顶部距离
dx: '', // 元素距离左侧的距离
dy: '', // 元素距离顶部的距离
xPum: '', // 元素移动的x轴距离
yPum: '', // 元素移动的y轴距离
}
},
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;
},
move(e){
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;
} else if(sumWidth > oWrapWidth){
moveDiv.style.left = oWrapWidth - oWidth + 'px';
} 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;
}
}
}
</script>
<style lang="less" scoped>
.drag {
position: absolute;
left: 0;
right: 0;
z-index: 999;
}
</style>
引入Demo
<Drag class="drag">
<div slot="drag-cont">订单记录</div>
</Drag>
<style>
.drag {
width: .6rem;
height: .6rem;
background-color: rgba(0, 0, 0,.55);
text-align: center;
line-height: .6rem;
font-size: .14rem;
color: #ffffff;
}
</style>
使用的时候,给组件添加类名,添加样式即可。
Vue拖拽组件的更多相关文章
- vue拖拽组件开发
vue拖拽组件开发 创建临时vue项目 先查看node和npm版本,怎么安装就不多多bb了 再安装vue-cli npm install vue-cli -g //全局安装 vue-cli 检测是否安 ...
- Vue.Draggable:基于 Sortable.js 的 Vue 拖拽组件使用中遇到的问题
Sortable.js 介绍 https://segmentfault.com/a/1190000008209715 项目中遇到的问题: A - 我需要在项目的拖拽组件中,使用背景 1 - 想到的第一 ...
- Vue 拖拽组件 vuedraggable 和 vue-dragging
一.描述 之前用 vue 写过一个在线的多二维码生成服务,体验地址:https://postbird.gitee.io/vue-online-qrcode/ 后面发现二维码多了之后有时候想要排序,需要 ...
- vue2-dragula vue拖拽组件
https://github.com/kristianmandrup/vue2-dragula git 地址 https://github.com/kristianmandrup/vue2-dragu ...
- Vue拖拽组件列表实现动态页面配置
需求描述 最近在做一个后台系统,有一个功能产品需求是页面分为左右两部分,通过右边的组件列表来动态配置左边的页面视图,并且左边由组件拼装起来的视图,可以实现上下拖拽改变顺序,也可以删除. 根据这个需求我 ...
- Vue 拖拽组件 vuedraggable 和 awe-dnd
vuedraggable:https://www.npmjs.com/package/vuedraggable awe-dnd:https://www.npmjs.com/package/awe-dn ...
- Vue 拖拽组件 vuedraggable 、 vue-dragging 、awe-dnd
参考链接:http://www.ptbird.cn/vue-draggable-dragging.html vue-draggable 学习和使用:https://www.jianshu.com/p/ ...
- Vue 可拖拽组件 Vue Smooth DnD 详解和应用演示
本文发布自 https://www.cnblogs.com/wenruo/p/15061907.html 转载请注明出处. 简介和 Demo 展示 最近需要有个拖拽列表的需求,发现一个简单好用的 Vu ...
- vue-slicksort拖拽组件
vue-slicksort拖拽组件 安装 通过npm安装 $ npm install vue-slicksort --save 通过yarn安装 $ yarn add vue-slicksort 插件 ...
随机推荐
- MongoDB(课时8 模运算)
3.4.2.3 求模 模运算使用“$mod”来完成,语法: {$mod : [除数,余数]} 范例:求模 db.students.find({"age" : {"$mod ...
- Netcat使用方法
netcat被誉为网络安全界的‘瑞士军刀',相信没有什么人不认识它吧...... 一个简单而有用的工具,透过使用TCP或UDP协议的网络连接去读写数据.它被设计成一个稳定的后门工具,能够直接由其它 ...
- URAL 2072 Kirill the Gardener 3
URAL 2072 思路: dp+离散化 由于湿度的范围很大,所以将湿度离散化 可以证明,先到一种湿度的最左端或者最右端,然后结束于最右端或最左端最优,因为如果结束于中间,肯定有重复走的路 状态:dp ...
- Python requests快速上手
Python requests快速上手 这里参考官方文档,在ide中写了一遍,加深一下印象,定义的函数只是为了方便区分不同的请求方式 #-*-coding:utf-8-*- # Time:2017/1 ...
- Android程序员眼中世界上最遥远的距离
世界上最遥远的距离,是我在if里你在else里,似乎一直相伴又永远分离: 世界上最痴心的等待,是我当case你是switch,或许永远都选不上自己: 世界上最真情的相依,是你在try我在catch. ...
- 『cs231n』RNN之理解LSTM网络
概述 LSTM是RNN的增强版,1.RNN能完成的工作LSTM也都能胜任且有更好的效果:2.LSTM解决了RNN梯度消失或爆炸的问题,进而可以具有比RNN更为长时的记忆能力.LSTM网络比较复杂,而恰 ...
- OAF中下载附件之后页面失效,报过时的数据异常,浏览器后退异常
我在使用了下载功能之后,再往页面添加行或进行保存,页面老是报浏览器后退的异常. 猜测是因为我的下载按钮使用的submitButton,它隐式的包含了一个submit动作,且我在代码中有一个Commit ...
- Session的方法getSession() 与 getSession(boolean para)区别
getSession(boolean para)返回当前http会话,如果不存在,则创建一个新的会话getSession() 调用getSession(true)的简化版 [官方解释] getSess ...
- 使用a标签实现软件下载及下载量统计
通常最简单的软件下载就是采用如下方式: <a id="welcomeMiddleBtn" href="${basePath}/files/client/instal ...
- iOS UI-QQ聊天布局
一.Model BWMessage.h #import <Foundation/Foundation.h> typedef enum{ BWMessageMe = ,//表示自己 BWMe ...