Add node resizing
This commit is contained in:
parent
823f3d7730
commit
9439dd2d95
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { Position } from '#shared/canvas.util';
|
||||
import type { Box, Position } from '#shared/canvas.util';
|
||||
type Direction = 'bottom' | 'top' | 'left' | 'right';
|
||||
const rotation: Record<Direction, string> = {
|
||||
top: "180",
|
||||
|
|
@ -11,7 +11,7 @@ const rotation: Record<Direction, string> = {
|
|||
interface ActionMap {
|
||||
move: Position;
|
||||
edit: string;
|
||||
resize: string;
|
||||
resize: Box;
|
||||
remove: CanvasNode | undefined;
|
||||
create: CanvasNode | undefined;
|
||||
property: CanvasNode;
|
||||
|
|
@ -211,6 +211,18 @@ function moveNode(index: number[], deltax: number, deltay: number)
|
|||
|
||||
addAction('move', actions);
|
||||
}
|
||||
function resizeNode(index: number[], deltax: number, deltay: number, deltaw: number, deltah: number)
|
||||
{
|
||||
const actions: HistoryAction<'resize'>[] = [];
|
||||
for(const i of index)
|
||||
{
|
||||
const node = canvas.value.nodes[i];
|
||||
|
||||
actions.push({ element: i, from: { x: node.x - deltax, y: node.y - deltay, w: node.width - deltaw, h: node.height - deltah }, to: { x: node.x, y: node.y, w: node.width, h: node.height } });
|
||||
}
|
||||
|
||||
addAction('resize', actions);
|
||||
}
|
||||
function selectNode(index: number)
|
||||
{
|
||||
if(focusing.value !== index)
|
||||
|
|
@ -297,6 +309,15 @@ const undo = () => {
|
|||
canvas.value.nodes[action.element].y = a.from.y;
|
||||
break;
|
||||
}
|
||||
case 'resize':
|
||||
{
|
||||
const a = action as HistoryAction<'resize'>;
|
||||
canvas.value.nodes[action.element].x = a.from.x;
|
||||
canvas.value.nodes[action.element].y = a.from.y;
|
||||
canvas.value.nodes[action.element].width = a.from.w;
|
||||
canvas.value.nodes[action.element].height = a.from.h;
|
||||
break;
|
||||
}
|
||||
case 'edit':
|
||||
{
|
||||
const a = action as HistoryAction<'edit'>;
|
||||
|
|
@ -345,6 +366,15 @@ const redo = () => {
|
|||
canvas.value.nodes[action.element].y = a.to.y;
|
||||
break;
|
||||
}
|
||||
case 'resize':
|
||||
{
|
||||
const a = action as HistoryAction<'resize'>;
|
||||
canvas.value.nodes[action.element].x = a.to.x;
|
||||
canvas.value.nodes[action.element].y = a.to.y;
|
||||
canvas.value.nodes[action.element].width = a.to.w;
|
||||
canvas.value.nodes[action.element].height = a.to.h;
|
||||
break;
|
||||
}
|
||||
case 'edit':
|
||||
{
|
||||
const a = action as HistoryAction<'edit'>;
|
||||
|
|
@ -504,7 +534,7 @@ useShortcuts({
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<CanvasNodeEditor v-for="(node, index) of canvas.nodes" :key="node.id" ref="nodes" :node="node" :index="index" :zoom="zoom" @select="selectNode" @edit="editNode" @move="(i, x, y) => moveNode([i], x, y)"/>
|
||||
<CanvasNodeEditor v-for="(node, index) of canvas.nodes" :key="node.id" ref="nodes" :node="node" :index="index" :zoom="zoom" @select="selectNode" @edit="editNode" @move="(i, x, y) => moveNode([i], x, y)" @resize="(i, x, y, w, h) => resizeNode([i], x, y, w, h)" />
|
||||
</div>
|
||||
<template v-for="edge of edges">
|
||||
<div :key="edge.id" v-if="edge.label" class="absolute z-10"
|
||||
|
|
|
|||
|
|
@ -7,22 +7,22 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-if="focusing">
|
||||
<span @mousedown="(e) => resizeNode(e, 0, -1)" id="n " class="cursor-n-resize absolute -top-3 -right-3 -left-3 h-6 group">
|
||||
<span @mousedown="(e) => dragEdge(e, 'top')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -top-1.5 left-1/2 -translate-x-3"></span>
|
||||
<span @mousedown.left="(e) => resizeNode(e, 0, 1, 0, -1)" id="n " class="cursor-n-resize absolute -top-3 -right-3 -left-3 h-6 group">
|
||||
<span @mousedown.left="(e) => dragEdge(e, 'top')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -top-1.5 left-1/2 -translate-x-3"></span>
|
||||
</span> <!-- North -->
|
||||
<span @mousedown="(e) => resizeNode(e, 0, 1)" id="s " class="cursor-s-resize absolute -bottom-3 -right-3 -left-3 h-6 group">
|
||||
<span @mousedown="(e) => dragEdge(e, 'bottom')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -bottom-1.5 left-1/2 -translate-x-3"></span>
|
||||
<span @mousedown.left="(e) => resizeNode(e, 0, 0, 0, 1)" id="s " class="cursor-s-resize absolute -bottom-3 -right-3 -left-3 h-6 group">
|
||||
<span @mousedown.left="(e) => dragEdge(e, 'bottom')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -bottom-1.5 left-1/2 -translate-x-3"></span>
|
||||
</span> <!-- South -->
|
||||
<span @mousedown="(e) => resizeNode(e, 1, 0)" id="e " class="cursor-e-resize absolute -top-3 -bottom-3 -right-3 w-6 group">
|
||||
<span @mousedown="(e) => dragEdge(e, 'right')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -right-1.5 top-1/2 -translate-y-3"></span>
|
||||
<span @mousedown.left="(e) => resizeNode(e, 0, 0, 1, 0)" id="e " class="cursor-e-resize absolute -top-3 -bottom-3 -right-3 w-6 group">
|
||||
<span @mousedown.left="(e) => dragEdge(e, 'right')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -right-1.5 top-1/2 -translate-y-3"></span>
|
||||
</span> <!-- East -->
|
||||
<span @mousedown="(e) => resizeNode(e, -1, 0)" id="w " class="cursor-w-resize absolute -top-3 -bottom-3 -left-3 w-6 group">
|
||||
<span @mousedown="(e) => dragEdge(e, 'left')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -left-1.5 top-1/2 -translate-y-3"></span>
|
||||
<span @mousedown.left="(e) => resizeNode(e, 1, 0, -1, 0)" id="w " class="cursor-w-resize absolute -top-3 -bottom-3 -left-3 w-6 group">
|
||||
<span @mousedown.left="(e) => dragEdge(e, 'left')" :class="[style.bg]" class="hidden group-hover:block absolute rounded-full border-2 border-light-70 dark:border-dark-70 w-6 h-6 -left-1.5 top-1/2 -translate-y-3"></span>
|
||||
</span> <!-- West -->
|
||||
<span @mousedown="(e) => resizeNode(e, 1, -1)" id="nw" class="cursor-nw-resize absolute -top-4 -left-4 w-8 h-8"></span> <!-- North West -->
|
||||
<span @mousedown="(e) => resizeNode(e, -1, -1)" id="ne" class="cursor-ne-resize absolute -top-4 -right-4 w-8 h-8"></span> <!-- North East -->
|
||||
<span @mousedown="(e) => resizeNode(e, -1, 1)" id="se" class="cursor-se-resize absolute -bottom-4 -right-4 w-8 h-8"></span> <!-- South East -->
|
||||
<span @mousedown="(e) => resizeNode(e, 1, 1)" id="sw" class="cursor-sw-resize absolute -bottom-4 -left-4 w-8 h-8"></span> <!-- South West -->
|
||||
<span @mousedown.left="(e) => resizeNode(e, 1, 1, -1, -1)" id="nw" class="cursor-nw-resize absolute -top-4 -left-4 w-8 h-8"></span> <!-- North West -->
|
||||
<span @mousedown.left="(e) => resizeNode(e, 0, 1, 1, -1)" id="ne" class="cursor-ne-resize absolute -top-4 -right-4 w-8 h-8"></span> <!-- North East -->
|
||||
<span @mousedown.left="(e) => resizeNode(e, 0, 0, 1, 1)" id="se" class="cursor-se-resize absolute -bottom-4 -right-4 w-8 h-8"></span> <!-- South East -->
|
||||
<span @mousedown.left="(e) => resizeNode(e, 1, 0, -1, 1)" id="sw" class="cursor-sw-resize absolute -bottom-4 -left-4 w-8 h-8"></span> <!-- South West -->
|
||||
</div>
|
||||
</div>
|
||||
<div v-else style="outline-style: solid;" :class="[style.border, style.outline, { '!outline-4': focusing }]" class="outline-0 transition-[outline-width] border-2 bg-light-20 dark:bg-dark-20 overflow-hidden contain-strict w-full h-full flex" >
|
||||
|
|
@ -47,9 +47,8 @@ const { node, index, zoom } = defineProps<{
|
|||
const emit = defineEmits<{
|
||||
(e: 'select', index: number): void,
|
||||
(e: 'edit', index: number): void,
|
||||
(e: 'resize', index: number): void,
|
||||
(e: 'move', index: number, x: number, y: number): void,
|
||||
(e: 'resize', index: number, x: number, y: number): void,
|
||||
(e: 'resize', index: number, x: number, y: number, w: number, h: number): void,
|
||||
}>();
|
||||
|
||||
const dom = useTemplateRef('dom');
|
||||
|
|
@ -73,9 +72,30 @@ function editNode(e: Event) {
|
|||
dom.value?.removeEventListener('mousedown', dragstart);
|
||||
emit('edit', index);
|
||||
}
|
||||
function resizeNode(e: Event, x: number, y: number) {
|
||||
function resizeNode(e: MouseEvent, x: number, y: number, w: number, h: number) {
|
||||
e.stopImmediatePropagation();
|
||||
emit('resize', index);
|
||||
|
||||
const startx = node.x, starty = node.y, startw = node.width, starth = node.height;
|
||||
const resizemove = (e: MouseEvent) => {
|
||||
if(e.button !== 0)
|
||||
return;
|
||||
|
||||
node.x += (e.movementX / zoom) * x;
|
||||
node.y += (e.movementY / zoom) * y;
|
||||
node.width += (e.movementX / zoom) * w;
|
||||
node.height += (e.movementY / zoom) * h;
|
||||
};
|
||||
const resizeend = (e: MouseEvent) => {
|
||||
if(e.button !== 0)
|
||||
return;
|
||||
emit('resize', index, node.x - startx, node.y - starty, node.width - startw, node.height - starth);
|
||||
|
||||
window.removeEventListener('mousemove', resizemove);
|
||||
window.removeEventListener('mouseup', resizeend);
|
||||
}
|
||||
|
||||
window.addEventListener('mousemove', resizemove);
|
||||
window.addEventListener('mouseup', resizeend);
|
||||
}
|
||||
function dragEdge(e: Event, direction: Direction) {
|
||||
e.stopImmediatePropagation();
|
||||
|
|
|
|||
BIN
db.sqlite-wal
BIN
db.sqlite-wal
Binary file not shown.
|
|
@ -3,6 +3,7 @@ import { clamp } from "#shared/general.utils";
|
|||
|
||||
export type Direction = 'bottom' | 'top' | 'left' | 'right';
|
||||
export type Position = { x: number, y: number };
|
||||
export type Box = Position & { w: number, h: number };
|
||||
export type Path = {
|
||||
path: string;
|
||||
from: Position;
|
||||
|
|
|
|||
Loading…
Reference in New Issue