前言
在工作中实现的一个元素上下拖拽的动效,给大家分享一下,其中用到了本地存储记录拖拽的历史坐标,用EventBus
做了拖拽时锁住点击方法(防止用户在拖拽鼠标松开后触发点击事件的方法),大家可根据自己的业务进行扩展修改
效果图
参数说明
参数 | 说明 | 默认值 |
---|---|---|
el | 需要被拖拽的元素 | |
value | 参数配置 |
value
详细参数说明
参数 | 说明 | 默认值 |
---|---|---|
vertical | 是否允许垂直滚动 | true |
horizontal | 是否允许水平滚动 | true |
arealimit | 是否开启边界限制 | false |
margintop | 拖拽到头部的距离 | 0 |
marginbottom | 拖拽到底部的距离 | 0 |
marginleft | 拖拽到左边的距离 | 0 |
marginright | 拖拽到右边的距离 | 0 |
以vue
为例子将方法挂载到mounted
中
mounted() {
drag(document.querySelector("#FeedBackPackMove"), {
horizontal: false,
arealimit: true,
margintop: 40,
marginbottom: 40,
});
}
挂载EventBus
接收拖拽信息
mounted() {
EventBus.$on('screen',(e) => {
this.screenX = e.screenX
this.screenY = e.screenY
})
EventBus.$on('isLock',(e) => {
const deviation = this.screenY - e.screenY
if(deviation <= 5 && deviation >= -5){//拖拽移动的范围,这里防止用户鼠标灵敏度太高,误触发点击事件
this.lock = false
}else{
this.lock = true
}
})
}
完整vue
代码
<template>
<div id="app">
<div :style="{top:FeedBackPackMove,height:'86px'}" id="FeedBackPackMove" @click.stop="curFn">
</div>
</div>
</template>
<script>
import {EventBus} from "./event-bus"
import {drag} from './drag'
export default {
name: 'App',
components: {
},
data () {
return {
FeedBackPackMove:localStorage.getItem('FeedBackPackMove'),//展开的距离
}
},
mounted() {
drag(document.querySelector("#FeedBackPackMove"), {
horizontal: false,
arealimit: true,
margintop: 40,
marginbottom: 40,
});
EventBus.$on('screen',(e) => {
this.screenX = e.screenX
this.screenY = e.screenY
})
EventBus.$on('isLock',(e) => {
const deviation = this.screenY - e.screenY
if(deviation <= 5 && deviation >= -5){//拖拽移动的范围,这里防止用户鼠标灵敏度太高,误触发点击事件
this.lock = false
}else{
this.lock = true
}
})
},
methods: {
//切换菜单
curFn() {
if(this.lock) return;//为true移动中,跳出方法
//切换菜单逻辑
}
}
}
</script>
<style>
#FeedBackPackMove{
position:fixed;
right: 0;
bottom: 20px;
width: 30px;
height: 86px;
background-color:#0077ff;
}
</style>
封装好的drag.js
文件
/**
* 元素可拖动方法
* @param {*} el 需要被拖拽的元素
* @param {*} value 配置参数
*/
import {EventBus} from "./event-bus"
export const drag = function(el, value = {}){
const config = {vertical: true, horizontal: true, arealimit: false, margintop: 0, marginbottom: 0, marginleft: 0, marginright: 0, ...value};
const _el = el;
_el.onmousedown = e => {
document.onselectstart = function() {
return false; //禁止选择网页上的文字
};
const disX = e.clientX - _el.offsetLeft; //鼠标按下,计算当前元素距离可视区的距离
const disY = e.clientY - _el.offsetTop;
EventBus.$emit('screen',e)//记录点击坐标
document.onmousemove = function(e) {
if (config.horizontal) {
const l = e.clientX - disX;
if (config.arealimit) {
if (l < config.marginleft) {
_el.style.left = config.marginleft + 'px';
} else if (l >= this.body.clientWidth - config.marginright) {
_el.style.left = this.body.clientWidth - config.marginright + 'px';
} else {
_el.style.left = l + 'px';
}
} else {
_el.style.left = l + 'px';
}
}
if (config.vertical) {
const t = e.clientY - disY;
const PM = document.querySelector('#FeedBackPackMove');//获取展开按钮元素
const PMH = parseInt(PM.style.height);//展开按钮元素的高度
if (config.arealimit) {
if (t < config.margintop) {//拉到头部
_el.style.top = config.margintop + 'px';
} else if (t >= document.documentElement.clientHeight - config.marginbottom - PMH) {//拉到底部,减去元素的高度
_el.style.top = document.documentElement.clientHeight - config.marginbottom - PMH + 'px';
}else {
_el.style.top = t + 'px';
}
localStorage.setItem('FeedBackPackMove',PM.style.top);//记录拖拽点
} else {
_el.style.top = t + 'px';
}
}
};
document.onmouseup = e => {
EventBus.$emit('isLock',e)
document.onmousemove = document.onmouseup = null;
document.onselectstart = null;
};
return false;
};
};
event-bus.js
文件
import Vue from 'vue'
// 事件总线(用于方便跨组件间的传值)
export const EventBus = new Vue()
结语
如果你觉得此文对你有一丁点帮助,麻烦点个赞哈,谢谢大家。