obsidian-visualiser/components/page/Canvas.vue

165 lines
5.6 KiB
Vue

<script lang="ts">
function cancelEvent(e: Event)
{
e.preventDefault();
}
</script>
<script setup lang="ts">
import { useDrag, useHover, usePinch, useWheel } from '@vueuse/gesture';
import type { CanvasContent } from '~/types/canvas';
import { Icon } from '@iconify/vue/dist/iconify.js';
import { clamp } from '#shared/general.utils';
type CanvasOverview = any;
const { overview } = defineProps<{
overview: CanvasOverview
}>();
const { data: canvas, status } = await useFetch(`/api/file/content/${encodeURIComponent(overview.path)}`, {
transform: (input) => input && input.content ? JSON.parse(input?.content) as CanvasContent : undefined
});
const { user } = useUserSession();
const isOwner = computed(() => user.value?.id === overview.owner);
const dispX = ref(0), dispY = ref(0), minZoom = ref(0.1), zoom = ref(0.5);
const canvasRef = useTemplateRef('canvasRef');
const reset = (_: MouseEvent) => {
zoom.value = minZoom.value;
dispX.value = 0;
dispY.value = 0;
}
/*
stroke-light-red
stroke-light-orange
stroke-light-yellow
stroke-light-green
stroke-light-cyan
stroke-light-purple
dark:stroke-dark-red
dark:stroke-dark-orange
dark:stroke-dark-yellow
dark:stroke-dark-green
dark:stroke-dark-cyan
dark:stroke-dark-purple
fill-light-red
fill-light-orange
fill-light-yellow
fill-light-green
fill-light-cyan
fill-light-purple
dark:fill-dark-red
dark:fill-dark-orange
dark:fill-dark-yellow
dark:fill-dark-green
dark:fill-dark-cyan
dark:fill-dark-purple
bg-light-red
bg-light-orange
bg-light-yellow
bg-light-green
bg-light-cyan
bg-light-purple
dark:bg-dark-red
dark:bg-dark-orange
dark:bg-dark-yellow
dark:bg-dark-green
dark:bg-dark-cyan
dark:bg-dark-purple
border-light-red
border-light-orange
border-light-yellow
border-light-green
border-light-cyan
border-light-purple
dark:border-dark-red
dark:border-dark-orange
dark:border-dark-yellow
dark:border-dark-green
dark:border-dark-cyan
dark:border-dark-purple
*/
const cancelEvent = (e: Event) => e.preventDefault()
useHover(({ hovering }) => {
if (!hovering) {
//@ts-ignore
window.removeEventListener('wheel', cancelEvent, { passive: false });
document.removeEventListener('gesturestart', cancelEvent)
document.removeEventListener('gesturechange', cancelEvent)
return
}
window.addEventListener('wheel', cancelEvent, { passive: false });
document.addEventListener('gesturestart', cancelEvent)
document.addEventListener('gesturechange', cancelEvent)
}, {
domTarget: canvasRef,
})
const dragHandler = useDrag(({ delta: [x, y] }: { delta: number[] }) => {
dispX.value += x / zoom.value;
dispY.value += y / zoom.value;
}, {
domTarget: canvasRef,
passive: true,
});
const wheelHandler = useWheel(({ delta: [x, y] }: { delta: number[] }) => {
zoom.value = clamp(zoom.value + y * -0.001, minZoom.value, 3);
}, {
domTarget: canvasRef,
passive: true,
});
const pinchHandler = usePinch(({ offset: [z] }: { offset: number[] }) => {
zoom.value = clamp(z / 2048, minZoom.value, 3);
}, {
domTarget: canvasRef,
passive: true,
});
</script>
<template>
<Loading v-if="status === 'pending'" />
<div v-else-if="canvas">
<div ref="canvasRef" 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="flex flex-col absolute sm:top-2 top-10 left-2 z-[35] overflow-hidden gap-4">
<div class="border border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10">
<Tooltip message="Zoom avant" side="right">
<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">
<Icon icon="radix-icons:plus" />
</div>
</Tooltip>
<Tooltip message="Reset" side="right">
<div @click="zoom = 1" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
<Icon icon="radix-icons:reload" />
</div>
</Tooltip>
<Tooltip message="Tout contenir" side="right">
<div @click="reset" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
<Icon icon="radix-icons:corners" />
</div>
</Tooltip>
<Tooltip message="Zoom arrière" side="right">
<div @click="zoom = clamp(zoom * 0.9, 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">
<Icon icon="radix-icons:minus" />
</div>
</Tooltip>
</div>
<div class="border border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10" v-if="isOwner">
<Tooltip message="Modifier" side="right">
<NuxtLink :to="{ name: 'explore-edit', hash: '#' + overview.path }" class="w-8 h-8 flex justify-center items-center p-2 hover:bg-light-30 dark:hover:bg-dark-30 cursor-pointer">
<Icon icon="radix-icons:pencil-1" />
</NuxtLink>
</Tooltip>
</div>
</div>
<CanvasRenderer :style="{transform: `scale(${zoom}) translate(${dispX}px, ${dispY}px)`}" :canvas="canvas" :zoom="zoom" />
</div>
</div>
</template>