Canvas CSS update

This commit is contained in:
2024-08-29 17:45:43 +02:00
parent c694d28982
commit 2a8abb4796
11 changed files with 108 additions and 69 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>