You've already forked obsidian-visualiser
Canvas CSS update
This commit is contained in:
@@ -1,43 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import type { CanvasColor } from "~/types/canvas";
|
||||
|
||||
type Direction = 'bottom' | 'top' | 'left' | 'right';
|
||||
interface Props
|
||||
{
|
||||
path: {
|
||||
path: string;
|
||||
from: { x: number; y: number };
|
||||
to: { x: number; y: number };
|
||||
side: 'bottom' | 'top' | 'left' | 'right';
|
||||
side: Direction;
|
||||
};
|
||||
color?: string;
|
||||
color?: CanvasColor;
|
||||
label?: string;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const rotation = {
|
||||
const rotation: Record<Direction, string> = {
|
||||
top: "180",
|
||||
bottom: "0",
|
||||
left: "90",
|
||||
right: "270"
|
||||
};
|
||||
|
||||
function hexToRgb(hex: string): string {
|
||||
return `${parseInt(hex.substring(1, 3), 16)}, ${parseInt(hex.substring(3, 5), 16)}, ${parseInt(hex.substring(5, 7), 16)}`;
|
||||
}
|
||||
|
||||
const classes: any = { 'is-themed': props.color !== undefined, 'mod-canvas-color-custom': (props?.color?.startsWith('#') ?? false) };
|
||||
|
||||
if (props.color !== undefined) {
|
||||
if (!props.color.startsWith('#'))
|
||||
classes['mod-canvas-color-' + props.color] = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<g :class="classes"
|
||||
:style="{ '--canvas-color': props?.color?.startsWith('#') ? hexToRgb(props.color) : undefined }">
|
||||
<path class="canvas-display-path" :d="props.path.path"></path>
|
||||
<g>
|
||||
<path :style="`stroke-linecap: butt; stroke-width: calc(3px * var(--zoom-multiplier)); --canvas-color: ${color?.hex}`" :class="(color?.class ?? undefined) ?? ((color && color?.hex !== undefined) ? 'stroke-[var(--canvas-color)]' : 'stroke-light-40 dark:stroke-dark-40')" class="fill-none stroke-[4px]" :d="path.path"></path>
|
||||
</g>
|
||||
<g :class="classes"
|
||||
:style="{ '--canvas-color': props?.color?.startsWith('#') ? hexToRgb(props.color) : undefined, transform: `translate(${props.path.to.x}px, ${props.path.to.y}px) rotate(${rotation[props.path.side]}deg)` }">
|
||||
<polygon class="canvas-path-end" points="0,0 6.5,10.4 -6.5,10.4"></polygon>
|
||||
<g :style="`transform: translate(${path.to.x}px, ${path.to.y}px) scale(var(--zoom-multiplier)) rotate(${rotation[path.side]}deg); --canvas-color: ${color?.hex}`">
|
||||
<polygon :class="(color?.class ?? undefined) ?? ((color && color?.hex !== undefined) ? 'fill-[var(--canvas-color)]' : 'fill-light-40 dark:fill-dark-40')" points="0,0 6.5,10.4 -6.5,10.4"></polygon>
|
||||
</g>
|
||||
</template>
|
||||
@@ -25,35 +25,20 @@ function darken(rgb: string): boolean
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const classes: Record<string, boolean> = { 'canvas-node-group': props.node.type === 'group', 'is-themed': props.node.color !== undefined, 'mod-canvas-color-custom': (props.node?.color?.startsWith('#') ?? false) };
|
||||
const size = Math.max(props.node.width, props.node.height);
|
||||
|
||||
if(props.node.color !== undefined)
|
||||
{
|
||||
if (!props.node.color.startsWith('#'))
|
||||
classes['mod-canvas-color-' + props.node.color] = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="canvas-node" :class="classes"
|
||||
:style="{transform: `translate(${node.x}px, ${node.y}px)`, width: `${node.width}px`, height: `${node.height}px`, '--canvas-node-width': `${node.width}px`, '--canvas-node-height': `${node.height}px`, '--canvas-color': node?.color?.startsWith('#') ? hexToRgb(node.color) : undefined}">
|
||||
<div class="canvas-node-container">
|
||||
<div class="absolute" :style="{transform: `translate(${node.x}px, ${node.y}px)`, width: `${node.width}px`, height: `${node.height}px`}">
|
||||
<div :class="{'z-0': node.type === 'group', 'z-[2]': node.type !== 'group'}" class="border-2 border-light-40 dark:border-dark-40 bg-light-20 dark:bg-dark-20 overflow-hidden contain-strict w-full h-full py-2 px-4 flex">
|
||||
<template v-if="node.type === 'group' || zoom > Math.min(0.38, 1000 / size)">
|
||||
<div class="canvas-node-content markdown-embed">
|
||||
<div v-if="node.text?.length > 0" class="markdown-embed-content node-insert-event" style="">
|
||||
<div
|
||||
class="markdown-preview-view markdown-rendered node-insert-event show-indentation-guide allow-fold-headings allow-fold-lists">
|
||||
<div class="markdown-preview-sizer markdown-preview-section">
|
||||
<Markdown v-model="node.text" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="node.text?.length > 0" class="flex items-center">
|
||||
<Markdown v-model="node.text" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="canvas-node-placeholder">
|
||||
<div class="canvas-icon-placeholder">
|
||||
<div class="flex flex-1 justify-center items-center bg-light-30 dark:bg-dark-30">
|
||||
<div class="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||
class="svg-icon lucide-align-left">
|
||||
@@ -65,8 +50,6 @@ if(props.node.color !== undefined)
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<ClientOnly><div v-if="node.type === 'group' && node.label !== undefined" class="canvas-group-label"
|
||||
:class="{ 'mod-foreground-dark': darken(getColor(props.node?.color ?? '')), 'mod-foreground-light': !darken(getColor(props.node?.color ?? ''))}">
|
||||
{{ node.label }}</div></ClientOnly>
|
||||
<div v-if="node.type === 'group' && node.label !== undefined" style="max-width: 100%; font-size: calc(16px * var(--zoom-multiplier))" class="origin-bottom-left tracking-wider truncate inline-block bg-light-40 dark:bg-dark-40 text-light-100 dark:text-dark-100 absolute bottom-[100%] mb-2 px-2 py-1 font-thin">{{ node.label }}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -47,7 +47,7 @@ const onResize = (event?: Event) => {
|
||||
maxX.value = _maxX = _maxX + 32;
|
||||
maxY.value = _maxY = _maxY + 32;
|
||||
|
||||
minZoom.value = Math.min((canvas.value?.clientWidth ?? 1920) / (_maxX - _minX), (canvas.value?.clientHeight ?? 1080) / (_maxY - _minY)) * 0.9;
|
||||
minZoom.value = Math.min((canvas.value?.clientWidth ?? 1920) / (_maxX - _minX), (canvas.value?.clientHeight ?? 1080) / (_maxY - _minY), 0.01) * 0.9;
|
||||
zoom.value = clamp(zoom.value, minZoom.value, 3);
|
||||
|
||||
bbox.value = (canvas.value ?? document.getElementById('canvas'))?.getBoundingClientRect();
|
||||
@@ -216,7 +216,7 @@ function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r:
|
||||
<Suspense>
|
||||
<template #default>
|
||||
<div id="canvas" ref="canvas" @pointerdown="onPointerDown" @wheel.passive="onWheel" @touchstart.passive="onTouchStart"
|
||||
@dragstart.prevent="" class="relative overflow-hidden"
|
||||
@dragstart.prevent="" class="absolute top-0 left-0 overflow-hidden w-full h-full"
|
||||
: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 top-2 left-2 z-[100] 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"
|
||||
@@ -257,18 +257,18 @@ function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r:
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="canvas"
|
||||
<div class="absolute top-0 left-0 w-full h-full origin-top pointer-events-none z-10"
|
||||
:style="{transform: `translate(${centerX}px, ${centerY}px) scale(${zoom}) translate(${dispX}px, ${dispY}px)`}">
|
||||
<svg class="canvas-edges">
|
||||
<svg class="absolute top-0 left-0 overflow-visible w-full h-full origin-top pointer-events-none z-[1]">
|
||||
<CanvasEdge v-for="edge of props.canvas.edges" :key="edge.id"
|
||||
:path="path(getNode(edge.fromNode)!, edge.fromSide, getNode(edge.toNode)!, edge.toSide)"
|
||||
:color="edge.color" :label="edge.label" />
|
||||
</svg>
|
||||
<CanvasNode v-for="node of props.canvas.nodes" :key="node.id" :node="node" :zoom="zoom" />
|
||||
<template v-for="edge of props.canvas.edges">
|
||||
<div :key="edge.id" v-if="edge.label" class="canvas-path-label-wrapper"
|
||||
<div :key="edge.id" v-if="edge.label" class="absolute z-10"
|
||||
:style="{ transform: labelCenter(getNode(edge.fromNode)!, edge.fromSide, getNode(edge.toNode)!, edge.toSide) }">
|
||||
<div class="canvas-path-label">{{ edge.label }}</div>
|
||||
<div class="relative bg-light-20 dark:bg-dark-20 border border-light-35 dark:border-dark-35 px-4 py-2 -translate-x-[50%] -translate-y-[50%]">{{ edge.label }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -278,4 +278,34 @@ function getCenter(n: { x: number, y: number }, i: { x: number, y: number }, r:
|
||||
<div class="loading"></div>
|
||||
</template>
|
||||
</Suspense>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.useless
|
||||
{
|
||||
@apply fill-light-red;
|
||||
@apply dark:fill-dark-red;
|
||||
@apply stroke-light-red;
|
||||
@apply dark:stroke-dark-red;
|
||||
@apply fill-light-orange;
|
||||
@apply dark:fill-dark-orange;
|
||||
@apply stroke-light-orange;
|
||||
@apply dark:stroke-dark-orange;
|
||||
@apply fill-light-yellow;
|
||||
@apply dark:fill-dark-yellow;
|
||||
@apply stroke-light-yellow;
|
||||
@apply dark:stroke-dark-yellow;
|
||||
@apply fill-light-green;
|
||||
@apply dark:fill-dark-green;
|
||||
@apply stroke-light-green;
|
||||
@apply dark:stroke-dark-green;
|
||||
@apply fill-light-cyan;
|
||||
@apply dark:fill-dark-cyan;
|
||||
@apply stroke-light-cyan;
|
||||
@apply dark:stroke-dark-cyan;
|
||||
@apply fill-light-purple;
|
||||
@apply dark:fill-dark-purple;
|
||||
@apply stroke-light-purple;
|
||||
@apply dark:stroke-dark-purple;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user