import {onMounted, onUnmounted, ref} from 'vue'
//返回的是拖拽元素的ref
const useDrag = ()=>{
const dRef = ref()
let isDragging = false
//记录鼠标在目标元素内与边缘的距离
let offsetY = 0;
let offsetX = 0;
let prePostion = {
x:0,
y:0
}
const handleMove = (e)=>{
if(isDragging && dRef.value){
//requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动
//使用定位可能会受外层的影响
requestAnimationFrame(()=>{
const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX
const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY
const left1 = prePostion.x + (clientX - offsetX);
const top1 = prePostion.y + (clientY - offsetY);
offsetX = clientX;
offsetY = clientY;
prePostion.x = left1;
prePostion.y = top1;
const maxX = window.innerWidth - (dRef.value.clientWidth || 0)
const maxY = window.innerHeight - (dRef.value.clientHeight || 0)
dRef.value.style.transform = `translate3d(${Math.min(left1,maxX)}px,${Math.min(top1,maxY)}px,0)`
// dRef.value.style.left = left + 'px';
// dRef.value.style.top = top + 'px';
// 禁用 div 上的点击事件,以避免拖拽时触发点击事件
dRef.value.style.pointerEvents = 'none';
})
}
//阻止事件的传播
e.stopPropagation()
e.preventDefault()
}
const handleMouseUp = (e)=>{
if(isDragging) {
window.removeEventListener('mousemove',handleMove,{
passive:false
})
window.removeEventListener('touchmove',handleMove,{
//阻止默认行为
passive:false
})
isDragging = false
}
}
const handleMoveStart = (e)=>{
//判断一下鼠标是否在目标元素里面
if(dRef.value){
const rect = dRef.value.getBoundingClientRect();
const {left,top,right,bottom} = rect
//判断是触摸嘛
const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX
const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY
if(clientX>=left && clientX<=right && clientY>=top && clientY<=bottom){
isDragging = true
offsetX = clientX;
offsetY = clientY;
dRef.value.style.transformOrigin = '0 0'
window.addEventListener('mousemove',handleMove,{
passive:false
})
window.addEventListener('touchmove',handleMove,{
//阻止默认行为
passive:false
})
// 添加鼠标松开和触摸结束事件监听器
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('touchend', handleMouseUp)
}
}
}
onMounted(()=>{
//添加鼠标按下的监听
if(dRef.value){
document.addEventListener('mousedown',handleMoveStart)
document.addEventListener('touchstart',handleMoveStart)
}
})
onUnmounted(()=>{
if(dRef.value){
dRef.value.removeEventListener('mousedown',handleMoveStart)
dRef.value.removeEventListener('touchstart',handleMoveStart)
}
document.removeEventListener('touchmove',handleMoveStart)
document.removeEventListener('mousemove',handleMoveStart)
})
return dRef
}
export default useDrag
Vue3实现拖拽的hook
最新推荐文章于 2024-09-13 14:34:15 发布