Visual improvement + code cleanup
This commit is contained in:
parent
6c0bfb9e4c
commit
f2261c3f35
|
|
@ -7,85 +7,7 @@ interface Props
|
|||
}
|
||||
const props = defineProps<Props>();
|
||||
|
||||
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[] }) => {
|
|||
|
||||
<template>
|
||||
<Suspense>
|
||||
<template #default> <!-- @pointerdown="onPointerDown" @touchstart="onTouchStart" -->
|
||||
<div id="canvas" v-drag="dragHandler" v-pinch="pinchHandler" v-wheel="wheelHandler"
|
||||
@dragstart.prevent="" class="absolute top-0 left-0 overflow-hidden w-full h-full touch-none"
|
||||
<template #default>
|
||||
<div id="canvas" v-drag="dragHandler" v-pinch="pinchHandler" v-wheel="wheelHandler" class="absolute top-0 left-0 overflow-hidden w-full h-full touch-none"
|
||||
:style="{ '--zoom-multiplier': (1 / Math.pow(zoom, 0.7)) }">
|
||||
<div class="border border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10 absolute sm:top-2 top-10 left-2 z-30 overflow-hidden">
|
||||
<div @click="zoom = clamp(zoom * 1.1, minZoom, 3)" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a>
|
||||
<span class="text-accent-blue inline-flex items-center cursor-pointer">
|
||||
<slot></slot>
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<h1 :id="parseId(id)" class="text-5xl font-thin mt-3 mb-8 first:pt-0 pt-2 relative sm:right-8 right-4">
|
||||
<h1 :id="parseId(id)" class="text-5xl font-thin mt-3 mb-8 first:pt-0 pt-2">
|
||||
<slot />
|
||||
</h1>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<h2 :id="parseId(id)" class="text-4xl font-semibold mt-3 mb-6 ms-1 first:pt-0 pt-2 relative sm:right-8 right-4">
|
||||
<h2 :id="parseId(id)" class="text-4xl font-semibold mt-3 mb-6 ms-1 first:pt-0 pt-2">
|
||||
<slot />
|
||||
</h2>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<template>
|
||||
<span class="before:content-['#'] cursor-default bg-accent-blue bg-opacity-10 hover:bg-opacity-20 text-accent-blue text-sm px-1 ms-1 pb-0.5 rounded-full rounded-se-none border border-accent-blue border-opacity-30">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</template>
|
||||
Loading…
Reference in New Issue