From 9e3756f81058c09d05b0b12cabc55cc769d9e1f0 Mon Sep 17 00:00:00 2001 From: draedful Date: Fri, 11 Oct 2024 03:31:30 +0300 Subject: [PATCH] playground: add examples and some perf improvements --- src/components/canvas/anchors/index.ts | 39 ++++++++------- src/services/newConnection/NewConnection.ts | 3 ++ src/stories/Playground/GraphPlayground.tsx | 50 +++++++++++++++++-- src/stories/Playground/GravityBlock/index.tsx | 9 ++-- src/utils/renderers/svgPath.ts | 19 ++++--- 5 files changed, 85 insertions(+), 35 deletions(-) diff --git a/src/components/canvas/anchors/index.ts b/src/components/canvas/anchors/index.ts index e50ecd2..1c8276e 100644 --- a/src/components/canvas/anchors/index.ts +++ b/src/components/canvas/anchors/index.ts @@ -102,6 +102,14 @@ export class Anchor extends withHitTest(EventedComponent) { public willIterate() { super.willIterate(); + + const { x, y, width, height } = this.hitBox.getRect(); + + this.shouldRender = width && height ? this.context.camera.isRectVisible(x, y, width, height) : true; + + } + + public didIterate(): void { const { x: poxX, y: posY } = this.props.getPosition(this.props); const hash = `${poxX}/${posY}/${this.shift}`; @@ -109,11 +117,6 @@ export class Anchor extends withHitTest(EventedComponent) { this.hitBoxHash = hash; this.debouncedSetHitBox(); } - - const { x, y, width, height } = this.hitBox.getRect(); - - this.shouldRender = width && height ? this.context.camera.isRectVisible(x, y, width, height) : true; - } public handleEvent(event: MouseEvent | KeyboardEvent) { @@ -155,19 +158,17 @@ export class Anchor extends withHitTest(EventedComponent) { return; } const { x, y } = this.props.getPosition(this.props); - render(this.context.ctx, (ctx) => { - ctx.save(); - ctx.fillStyle = this.context.colors.anchor.background; - ctx.beginPath(); - ctx.arc(x, y, this.state.size * 0.5, 0, 2 * Math.PI); - ctx.fill(); - - if (this.state.selected) { - ctx.strokeStyle = this.context.colors.anchor.selectedBorder; - ctx.lineWidth = this.props.lineWidth + 3; - ctx.stroke(); - } - ctx.closePath(); - }) + const ctx = this.context.ctx; + ctx.fillStyle = this.context.colors.anchor.background; + ctx.beginPath(); + ctx.arc(x, y, this.state.size * 0.5, 0, 2 * Math.PI); + ctx.fill(); + + if (this.state.selected) { + ctx.strokeStyle = this.context.colors.anchor.selectedBorder; + ctx.lineWidth = this.props.lineWidth + 3; + ctx.stroke(); + } + ctx.closePath(); } } diff --git a/src/services/newConnection/NewConnection.ts b/src/services/newConnection/NewConnection.ts index 5c87a4c..8069d5a 100644 --- a/src/services/newConnection/NewConnection.ts +++ b/src/services/newConnection/NewConnection.ts @@ -45,6 +45,7 @@ export class NewConnection extends Component { ctx.closePath(); }); render(this.context.ctx, (ctx) => { + ctx.beginPath(); ctx.fillStyle = "rgba(254, 190, 92, 1)"; ctx.roundRect(this.state.tx, this.state.ty - 12, 24, 24, 8); ctx.fill(); @@ -66,6 +67,8 @@ export class NewConnection extends Component { initialHeight: 16 }, ctx, { x: this.state.tx, y: this.state.ty - 12, width: 24, height: 24 }); } + + ctx.closePath(); }) } diff --git a/src/stories/Playground/GraphPlayground.tsx b/src/stories/Playground/GraphPlayground.tsx index 71fd573..4aae928 100644 --- a/src/stories/Playground/GraphPlayground.tsx +++ b/src/stories/Playground/GraphPlayground.tsx @@ -1,8 +1,8 @@ import "@gravity-ui/uikit/styles/styles.css"; -import { Flex, Text, ThemeProvider } from "@gravity-ui/uikit"; +import { Flex, Select, Text, ThemeProvider } from "@gravity-ui/uikit"; import React, { useCallback, useEffect, useLayoutEffect, useRef } from "react"; import { StoryFn } from "storybook/internal/types"; -import { Graph, GraphState } from "../../graph"; +import { Graph, GraphState, TGraphConfig } from "../../graph"; import { GraphBlock, GraphCanvas, GraphProps, useGraph, useGraphEvent } from "../../react-component"; import { ECanChangeBlockGeometry } from "../../store/settings"; import { useFn } from "../../utils/hooks/useFn"; @@ -11,7 +11,7 @@ import { TBlock } from "../../components/canvas/blocks/Block"; import { random } from "../../components/canvas/blocks/generate"; import { EAnchorType } from "../configurations/definitions"; import { ConfigEditor, ConfigEditorController } from "./Editor"; -import { createPlaygroundBlock, generatePlaygroundLayout, GravityBlockIS } from "./generateLayout"; +import { createPlaygroundBlock, generatePlaygroundLayout, GravityBlockIS, TGravityBlock } from "./generateLayout"; import { GravityBlock } from "./GravityBlock"; import './Playground.css'; import { GraphSettings } from "./Settings"; @@ -83,6 +83,7 @@ export function GraphPLayground() { editorRef?.current.updateBlocks([block]); editorRef?.current.scrollTo(block.id); }); + useGraphEvent(graph, "blocks-selection-change", ({ changes }) => { editorRef?.current.updateBlocks([ ...changes.add.map((id) => ({ @@ -197,11 +198,52 @@ export function GraphPLayground() { return () => document.body.removeEventListener('keydown', fn); }); + const updateExample = useFn(([value]) => { + let config: TGraphConfig; + switch(value) { + case "null": { + return; + } + case "1": { + config = generatePlaygroundLayout(0, 5); + break; + } + case "100": { + config = generatePlaygroundLayout(10, 100); + break; + } + case "1000": { + config = generatePlaygroundLayout(23, 150); + break; + } + case "10000": { + graph.updateSettings({ + useBezierConnections: false + }); + config = generatePlaygroundLayout(50, 150); + break; + } + } + console.log(config.blocks.length, config.connections.length) + setEntities(config); + graph.zoomTo('center', {transition: 500}); + updateVisibleConfig(); + }) + return ( - Graph viewer + + Graph viewer + + diff --git a/src/stories/Playground/GravityBlock/index.tsx b/src/stories/Playground/GravityBlock/index.tsx index 92afc60..411899e 100644 --- a/src/stories/Playground/GravityBlock/index.tsx +++ b/src/stories/Playground/GravityBlock/index.tsx @@ -120,9 +120,11 @@ export class GravityBlock extends CanvasBlock { } public renderMinimalisticBlock(ctx: CanvasRenderingContext2D): void { - render(ctx, (ctx) => { this.renderBody(ctx); - ctx.beginPath(); + // do not show icon for large scale + if(this.context.camera.getCameraScale() < 0.1) { + return; + } ctx.fillStyle = "rgba(255, 190, 92, 1)"; renderSVG({ @@ -132,8 +134,6 @@ export class GravityBlock extends CanvasBlock { iniatialWidth: 14, initialHeight: 14, }, ctx, this.getContentRect()); - ctx.closePath(); - }) } public renderDetailedView(ctx: CanvasRenderingContext2D) { @@ -152,6 +152,5 @@ export class GravityBlock extends CanvasBlock { ctx.textAlign = "center"; this.renderTextAtCenter(this.state.name, ctx); } - ctx.closePath(); } } \ No newline at end of file diff --git a/src/utils/renderers/svgPath.ts b/src/utils/renderers/svgPath.ts index a734cb9..70c3eb7 100644 --- a/src/utils/renderers/svgPath.ts +++ b/src/utils/renderers/svgPath.ts @@ -1,3 +1,5 @@ +import { render } from "./render"; + export function renderSVG( icon: { path: string, @@ -10,11 +12,14 @@ export function renderSVG( rect: {x: number, y: number, width: number, height: number}, ) { - const iconPath = new Path2D(icon.path); - const coefX = icon.width / icon.iniatialWidth; - const coefY = icon.height / icon.initialHeight; - // MoveTo position - ctx.translate(rect.x + (rect.width / 2) - (icon.width / 2), rect.y + (rect.height / 2) - (icon.height / 2)); - ctx.scale(coefX, coefY); - ctx.fill(iconPath, 'evenodd'); + render(ctx, (ctx) => { + const iconPath = new Path2D(icon.path); + const coefX = icon.width / icon.iniatialWidth; + const coefY = icon.height / icon.initialHeight; + // MoveTo position + ctx.translate(rect.x + (rect.width / 2) - (icon.width / 2), rect.y + (rect.height / 2) - (icon.height / 2)); + ctx.scale(coefX, coefY); + ctx.fill(iconPath, 'evenodd'); + }) + }