本文需要实现点击拖动元素时,元素在指定元素窗口内拖动,不能超出窗口,并且做节流优化避免事件触发太多次导致的性能问题,css动画使元素移动更流畅,上代码
我们的元素
<div id="app">
<div id="moveBox" :style="{'left': position.left, 'top': position.top}" @mousedown="handleMouseDown"></div>
</div>
样式
#moveBox{
z-index: 9999;
top: 100px;
left: 100px;
position: fixed;
width: 320px;
height: 460px;
background: #ffffff;
box-shadow: 0px 8px 30px 0px rgba(0, 44, 102, 0.2);
border-radius: 4px;
transition-property: left , top;
transition-duration: .2s , .2s;
}
准备一个节流函数
function throttle(func, delay = 100) {
let timer = null,
startTime = Date.now();
return function() {
let curTime = Date.now(),
remaining = delay - (curTime - startTime),
context = this,
args = arguments;
clearTimeout(timer);
if (remaining <= 0) {
func.apply(context, args);
startTime = Date.now();
} else {
timer = setTimeout(func, remaining);
}
}
}
vue js部分代码
export default {
data() {
return {
position: {
left: '100px',
top: '100px'
}
};
},
methods: {
handleMouseDown(e) {
let odiv = document.getElementById('moveBox'),
appDiv = document.getElementById('app'),
disX = e.clientX - odiv.offsetLeft, // 算出鼠标相对元素的位置
disY = e.clientY - odiv.offsetTop;
const throttleMove = throttle(event => {
if (!event) return;
// 鼠标按下并移动的事件
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
// 移动当前元素
let left = event.clientX - disX,
top = event.clientY - disY,
widthThreshold = appDiv.offsetWidth - odiv.offsetWidth,
heightThreshold = appDiv.offsetHeight - odiv.offsetHeight;
if (left < 0) {
left = 0;
} else if (left > widthThreshold) {
left = widthThreshold;
}
if (top < 0) {
top = 0;
} else if(top > heightThreshold) {
top = heightThreshold;
}
this.position.left = left + 'px';
this.position.top = top + 'px';
}, 100);
document.onmousemove = throttleMove;
document.onmouseup = _ => {
document.onmousemove = null;
document.onmouseup = null;
};
}
}
}
这样实现的效果,拖动元素时不会出现一卡一卡的效果,比较流畅,并且每秒触发的事件会很少性能上会有很大的提升