kindergarten_java/reading-platform-frontend/src/components/PressDrag.vue

142 lines
4.4 KiB
Vue
Raw Normal View History

2026-03-17 14:17:21 +08:00
<template>
<div ref="" id="draggableElementView" class="draggable-box cursor-grab" :style="elementStyle"
@mousedown.passive="handleStart" @touchstart.passive="handleStart" @click="handleClick">
<slot></slot>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, onUnmounted } from 'vue';
import { addResizeTimeOut, removeResizeTimeOut } from '@/utils';
export default defineComponent({
name: 'PressDragComponent',
emits: ['click'],
props: {
storageKey: {
default: '',
},
},
setup(props, { emit }) {
const view = {
offsetWidth: 50,
offsetHeight: 50,
innerWidth: 750,
innerHeight: 1280,
};
const storageKeyVal = `_tem_drag_${props.storageKey}`;
const initil = () => {
const node = document.querySelector('#draggableElementView') as HTMLElement;
view.offsetWidth = node.offsetWidth;
view.offsetHeight = node.offsetHeight;
view.innerWidth =
window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
view.innerHeight =
window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
};
addResizeTimeOut(initil);
const isDragging = ref(false);
const pressTimer = ref<number | null>(null);
const startTime = ref(0);
const elementStyle = ref<any>({
userSelect: 'none',
touchAction: 'none',
});
onMounted(() => {
nextTick(() => {
initil();
// if (props.storageKey && props.storageKey.length > 0) {
// let storageVal: any = localStorage.getItem(storageKeyVal);
// if (storageVal && storageVal.length > 0) {
// storageVal = storageVal.split(',');
// setStyle(storageVal[0], storageVal[1]);
// }
// }
});
});
const handleStart = (e: MouseEvent | TouchEvent) => {
e.preventDefault();
startTime.value = Date.now();
pressTimer.value = window.setTimeout(() => {
isDragging.value = true;
document.addEventListener('mousemove', handleDrag);
document.addEventListener('touchmove', handleDrag, { passive: false });
document.addEventListener('mouseup', handleEnd);
document.addEventListener('touchend', handleEnd);
}, 200);
};
const handleDrag = (e: MouseEvent | TouchEvent) => {
if (!isDragging.value) return;
e.preventDefault();
const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;
let left = clientX - view.offsetWidth / 2;
let top = clientY - view.offsetHeight / 2;
left = left > view.innerWidth - view.offsetWidth ? view.innerWidth - view.offsetWidth : left;
top = top > view.innerHeight - view.offsetHeight ? view.innerHeight - view.offsetHeight : top;
setStyle(left, top);
};
const setStyle = (left: number, top: number) => {
if (props.storageKey && props.storageKey.length > 0) {
localStorage.setItem(storageKeyVal, [left, top].join(','));
}
// if (left > innerWidth - 90) {
// left = innerWidth - 90;
// } else if (left < 30) {
// left = 30;
// }
// if (top > innerHeight - 90) {
// top = innerHeight - 90;
// } else if (top < 30) {
// top = 30;
// }
left = (left / view.innerWidth) * 100;
left = left < 0 ? 0 : left;
top = (top / view.innerHeight) * 100;
top = top < 0 ? 0 : top;
elementStyle.value = {
...elementStyle.value,
left: `${left}%`,
top: `${top}%`,
};
};
const handleEnd = () => {
clearTimeout(pressTimer.value!);
document.removeEventListener('mousemove', handleDrag);
document.removeEventListener('touchmove', handleDrag);
document.removeEventListener('mouseup', handleEnd);
document.removeEventListener('touchend', handleEnd);
isDragging.value = false;
};
const handleClick = (e: MouseEvent) => {
if (Date.now() - startTime.value > 200) return;
emit('click', e);
};
onUnmounted(() => {
handleEnd();
removeResizeTimeOut(initil);
});
return { elementStyle, handleStart, handleClick };
},
});
</script>
<style scoped>
/* .draggable-box {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.1s, box-shadow 0.3s;
} */
.draggable-box:active {
transform: scale(0.98);
}
</style>