vue3 hook 小球拖拽
先用react试了下, 搞了几个小时都没做出来想要的样子, 用vue3半个小时弄好了
react很多时候你觉得这么做没问题, 但是当你写了代码就会出问题, vue很多时候很符合直觉, 就算出错了, 也能根据经验和直觉快速定位
也可能是react用的太少, 毕竟也就不到一个月….
<template>
<div ref="startRef" class="box"></div>
<div ref="endRef" class="box"></div>
<svg class="svg">
<line
class="line"
:x1="linePosition.x1"
:x2="linePosition.x2"
:y1="linePosition.y1"
:y2="linePosition.y2"
></line>
</svg>
</template>
<script>
import { ref, onMounted, reactive, onUpdated, watch, computed } from "vue";
const useDrag = (dom, positionRef) => {
let mouseStart = reactive({ x: 0, y: 0 });
const { x, y, width, height } = dom.getBoundingClientRect();
let domStart = reactive({ x, y });
const down = ({ pageX, pageY }) => {
console.log("down");
document.addEventListener("mousemove", move);
document.addEventListener("mouseup", up);
const { x, y } = dom.getBoundingClientRect();
domStart = { x, y };
mouseStart = { x: pageX, y: pageY };
};
const up = () => {
console.log("up");
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", up);
};
const move = ({ pageX, pageY }) => {
const nx = domStart.x + pageX - mouseStart.x;
const ny = domStart.y + pageY - mouseStart.y;
dom.style.left = nx + "px";
dom.style.top = ny + "px";
positionRef.value = {
x: nx + width / 2,
y: ny + height / 2,
};
console.log("move");
};
positionRef.value = {
x: x + width / 2,
y: y + height / 2,
};
dom.addEventListener("mousedown", down);
};
export default {
name: "A",
setup() {
const startRef = ref(null);
const endRef = ref(null);
const startPositionRef = ref({ x: 0, y: 0 });
const endPositionRef = ref({ x: 0, y: 0 });
onMounted(() => {
useDrag(startRef.value, startPositionRef);
useDrag(endRef.value, endPositionRef);
});
watch([startPositionRef, endPositionRef], () => {
console.log("position changed");
});
const linePosition = computed(() => {
return {
x1: startPositionRef.value.x,
y1: startPositionRef.value.y,
x2: endPositionRef.value.x,
y2: endPositionRef.value.y,
};
});
return {
startRef,
endRef,
linePosition,
};
},
};
</script>
<style>
body,
html {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
}
.box {
width: 30px;
height: 30px;
border-radius: 50%;
position: absolute;
cursor: pointer;
background: black;
user-select: none;
}
.svg {
width: 100vw;
height: 100vh;
}
.line {
stroke: deeppink;
stroke-width: 2px;
}
</style>