diff --git a/components/canvas/CanvasRenderer.vue b/components/canvas/CanvasRenderer.vue index a19981d..26e9d24 100644 --- a/components/canvas/CanvasRenderer.vue +++ b/components/canvas/CanvasRenderer.vue @@ -7,85 +7,7 @@ interface Props } const props = defineProps(); -let dragging = false, posX = 0, posY = 0, dispX = ref(0), dispY = ref(0), minZoom = ref(0.1), zoom = ref(0.5); - -let lastDistance = 0; -let lastClickTime = 0; - -const onPointerDown = (event: PointerEvent) => { - if (event.isPrimary === false) return; - dragging = true; - - const now = performance.now(); - if(now - lastClickTime < 500 && Math.abs(event.clientX - posX) < 20 && Math.abs(event.clientY - posY) < 20) - { - if(event.ctrlKey) - { - zoom.value = clamp(zoom.value * 0.9, minZoom.value, 3); - } - else - { - zoom.value = clamp(zoom.value * 1.1, minZoom.value, 3); - } - } - lastClickTime = now; - - posX = event.clientX; - posY = event.clientY; - - document.addEventListener('pointermove', onPointerMove); - document.addEventListener('pointerup', onPointerUp); -} - -const onPointerMove = (event: PointerEvent) => { - if (event.isPrimary === false || dragging === false) return; - dispX.value -= (posX - event.clientX) / zoom.value; - dispY.value -= (posY - event.clientY) / zoom.value; - - posX = event.clientX; - posY = event.clientY; -} - -const onPointerUp = (event: PointerEvent) => { - if (event.isPrimary === false) return; - dragging = false; - document.removeEventListener('pointermove', onPointerMove); - document.removeEventListener('pointerup', onPointerUp); -} - -const onWheel = (event: WheelEvent) => { - - zoom.value = clamp(zoom.value + (event.deltaY * -0.001), minZoom.value, 3); -} - -const onTouchStart = (event: TouchEvent) => { - if(event.touches?.length === 2) - { - dragging = false; - lastDistance = length(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY); - - document.addEventListener('touchmove', onTouchMove); - document.addEventListener('touchend', onTouchEnd); - } -} - -const onTouchEnd = (event: TouchEvent) => { - if(event.touches?.length !== 2) - dragging = true; - - document.removeEventListener('touchmove', onTouchMove); - document.removeEventListener('touchend', onTouchEnd); -} - -const onTouchMove = (event: TouchEvent) => { - if(event.touches?.length === 2) - { - const distance = length(event.touches[0].clientX, event.touches[0].clientY, event.touches[1].clientX, event.touches[1].clientY); - zoom.value = clamp(zoom.value * (distance / lastDistance), minZoom.value, 3); - - lastDistance = distance; - } -} +const dispX = ref(0), dispY = ref(0), minZoom = ref(0.1), zoom = ref(0.5); const reset = (_: MouseEvent) => { zoom.value = minZoom.value; @@ -100,30 +22,27 @@ function clamp(x: number, min: number, max: number): number { return min; return x; } -function length(x1: number, y1: number, x2: number, y2: number): number { - return Math.sqrt((x2 - x1)^2 + (y2 - y1)^2); -} -function edgePos(side: 'bottom' | 'top' | 'left' | 'right', pos: { x: number, y: number }, n: number): { x: number, y: number } { +function edgePos(side: 'bottom' | 'top' | 'left' | 'right', pos: { x: number, y: number }, offset: number): { x: number, y: number } { switch (side) { case "left": return { - x: pos.x - n, + x: pos.x - offset, y: pos.y }; case "right": return { - x: pos.x + n, + x: pos.x + offset, y: pos.y }; case "top": return { x: pos.x, - y: pos.y - n + y: pos.y - offset }; case "bottom": return { x: pos.x, - y: pos.y + n + y: pos.y + offset } } } @@ -131,7 +50,7 @@ function getNode(id: string): CanvasNode | undefined { return props.canvas.nodes.find(e => e.id === id); } -function mK(e: { minX: number, minY: number, maxX: number, maxY: number }, t: 'bottom' | 'top' | 'left' | 'right'): { x: number, y: number } { +function posFromDir(e: { minX: number, minY: number, maxX: number, maxY: number }, t: 'bottom' | 'top' | 'left' | 'right'): { x: number, y: number } { switch (t) { case "top": return { x: (e.minX + e.maxX) / 2, y: e.minY }; @@ -156,9 +75,8 @@ function path(from: CanvasNode, fromSide: 'bottom' | 'top' | 'left' | 'right', t toSide: '', } } - const a = mK(getBbox(from), fromSide), - l = mK(getBbox(to), toSide); - return bezier(a, fromSide, l, toSide); + const start = posFromDir(getBbox(from), fromSide), end = posFromDir(getBbox(to), toSide); + return bezier(start, fromSide, end, toSide); } function bezier(from: { x: number, y: number }, fromSide: 'bottom' | 'top' | 'left' | 'right', to: { x: number, y: number }, toSide: 'bottom' | 'top' | 'left' | 'right'): any { const r = Math.hypot(from.x - to.x, from.y - to.y), o = clamp(r / 2, 70, 150), a = edgePos(fromSide, from, o), s = edgePos(toSide, to, o); @@ -170,9 +88,9 @@ function bezier(from: { x: number, y: number }, fromSide: 'bottom' | 'top' | 'le }; } function labelCenter(from: CanvasNode, fromSide: 'bottom' | 'top' | 'left' | 'right', to: CanvasNode, toSide: 'bottom' | 'top' | 'left' | 'right'): string { - const a = mK(getBbox(from), fromSide), l = mK(getBbox(to), toSide); - const r = Math.hypot(a.x - l.x, a.y - l.y), o = clamp(r / 2, 70, 150), b = edgePos(fromSide, a, o), s = edgePos(toSide, l, o); - const center = getCenter(a, l, b, s, 0.5); + const start = posFromDir(getBbox(from), fromSide), end = posFromDir(getBbox(to), toSide); + const len = Math.hypot(start.x - end.x, start.y - end.y), offset = clamp(len / 2, 70, 150), b = edgePos(fromSide, start, offset), s = edgePos(toSide, end, offset); + const center = getCenter(start, end, b, s, 0.5); return `translate(${center.x}px, ${center.y}px)`; } function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r: { x: number, y: number }, o: { x: number, y: number }, e: number): { x: number, y: number } { @@ -249,9 +167,8 @@ const wheelHandler = ({ delta: [x, y] }: { delta: number[] }) => {