diff --git a/src/Components/Canvas/Canvas.tsx b/src/Components/Canvas/Canvas.tsx index 708b5cd..0f732a4 100644 --- a/src/Components/Canvas/Canvas.tsx +++ b/src/Components/Canvas/Canvas.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef } from 'react'; -import { IPoint } from '../../Interfaces/IPoint'; +import { type IPoint } from '../../Interfaces/IPoint'; import { BAR_WIDTH } from '../Bar/Bar'; interface ICanvasProps { @@ -10,7 +10,12 @@ interface ICanvasProps { style?: React.CSSProperties }; -function UseCanvas(draw: (context: CanvasRenderingContext2D, frameCount: number, scale: number, translatePos: IPoint) => void): React.RefObject { +function UseCanvas( + draw: (context: CanvasRenderingContext2D, + frameCount: number, + scale: number, + translatePos: IPoint) => void +): React.RefObject { const canvasRef = useRef(null); const frameCount = useRef(0); const translatePos = useRef({ diff --git a/src/Components/Canvas/Dimension.ts b/src/Components/Canvas/Dimension.ts index e95fc92..639bc2d 100644 --- a/src/Components/Canvas/Dimension.ts +++ b/src/Components/Canvas/Dimension.ts @@ -1,4 +1,5 @@ import { NOTCHES_LENGTH } from '../../utils/default'; +import { IDimensionStyle } from '../SVG/Elements/Dimension'; interface IDimensionProps { id: string @@ -7,7 +8,7 @@ interface IDimensionProps { xEnd: number yEnd: number text: string - strokeWidth: number + style: IDimensionStyle scale?: number } @@ -26,8 +27,11 @@ function ApplyParametric(x0: number, t: number, vx: number): number { export function RenderDimension(ctx: CanvasRenderingContext2D, props: IDimensionProps): void { const scale = props.scale ?? 1; - const strokeStyle = 'black'; - const lineWidth = 2 / scale; + const strokeStyle = props.style.color ?? 'black'; + const lineWidth = (props.style.width ?? 2) / scale; + const dashArray: number[] = props.style.dashArray?.split(' ') + .flatMap(array => array.split(',')) + .map(stringValue => parseInt(stringValue)) ?? []; /// We need to find the points of the notches // Get the vector of the line @@ -59,6 +63,7 @@ export function RenderDimension(ctx: CanvasRenderingContext2D, props: IDimension ctx.lineWidth = lineWidth; ctx.strokeStyle = strokeStyle; ctx.fillStyle = strokeStyle; + ctx.setLineDash(dashArray); ctx.moveTo(startTopX, startTopY); ctx.lineTo(startBottomX, startBottomY); ctx.stroke(); @@ -68,6 +73,7 @@ export function RenderDimension(ctx: CanvasRenderingContext2D, props: IDimension ctx.moveTo(endTopX, endTopY); ctx.lineTo(endBottomX, endBottomY); ctx.stroke(); + ctx.setLineDash([]); const textX = (props.xStart + props.xEnd) / 2; const textY = (props.yStart + props.yEnd) / 2; ctx.font = `${16 / scale}px Verdana`; diff --git a/src/Components/Canvas/DimensionLayer.ts b/src/Components/Canvas/DimensionLayer.ts index 1b40961..bf4bc35 100644 --- a/src/Components/Canvas/DimensionLayer.ts +++ b/src/Components/Canvas/DimensionLayer.ts @@ -1,13 +1,11 @@ import { Orientation } from '../../Enums/Orientation'; import { Position } from '../../Enums/Position'; -import { IContainerModel } from '../../Interfaces/IContainerModel'; +import { type IContainerModel } from '../../Interfaces/IContainerModel'; import { SHOW_SELF_DIMENSIONS, SHOW_BORROWER_DIMENSIONS, SHOW_CHILDREN_DIMENSIONS } from '../../utils/default'; import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../utils/itertools'; import { TransformX, TransformY } from '../../utils/svg'; import { RenderDimension } from './Dimension'; -const MODULE_STROKE_WIDTH = 1; - export function AddDimensions( ctx: CanvasRenderingContext2D, containers: Map, @@ -18,7 +16,8 @@ export function AddDimensions( depth: number ): void { ctx.beginPath(); - if (SHOW_SELF_DIMENSIONS && container.properties.dimensionOptions.selfDimensions.positions.length > 0) { + if (SHOW_SELF_DIMENSIONS && + container.properties.dimensionOptions.selfDimensions.positions.length > 0) { ActionByPosition( ctx, dimMapped, @@ -32,7 +31,8 @@ export function AddDimensions( ); } - if (SHOW_BORROWER_DIMENSIONS && container.properties.dimensionOptions.dimensionWithMarks.positions.length > 0) { + if (SHOW_BORROWER_DIMENSIONS && + container.properties.dimensionOptions.dimensionWithMarks.positions.length > 0) { ActionByPosition( ctx, dimMapped, @@ -48,7 +48,9 @@ export function AddDimensions( ); } - if (SHOW_CHILDREN_DIMENSIONS && container.properties.dimensionOptions.childrenDimensions.positions.length > 0 && container.children.length >= 2) { + if (SHOW_CHILDREN_DIMENSIONS && + container.properties.dimensionOptions.childrenDimensions.positions.length > 0 && + container.children.length >= 2) { ActionByPosition( ctx, dimMapped, @@ -108,6 +110,7 @@ function AddHorizontalChildrenDimension( scale: number ): void { const childrenId = `dim-y${yDim.toFixed(0)}-children-${container.properties.id}`; + const style = container.properties.dimensionOptions.childrenDimensions; const lastChildId = container.children[container.children.length - 1]; const lastChild = FindContainerById(containers, lastChildId); @@ -115,8 +118,14 @@ function AddHorizontalChildrenDimension( if (lastChild === undefined) { return; } - let xChildrenStart = TransformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.positionReference); - let xChildrenEnd = TransformX(lastChild.properties.x, lastChild.properties.width, lastChild.properties.positionReference); + let xChildrenStart = TransformX( + lastChild.properties.x, + lastChild.properties.width, + lastChild.properties.positionReference); + let xChildrenEnd = TransformX( + lastChild.properties.x, + lastChild.properties.width, + lastChild.properties.positionReference); // Find the min and max for (let i = container.children.length - 2; i >= 0; i--) { @@ -152,9 +161,9 @@ function AddHorizontalChildrenDimension( xEnd: xChildrenEnd + offset, yStart: yDim, yEnd: yDim, - strokeWidth: MODULE_STROKE_WIDTH, text: textChildren, - scale + scale, + style }); } @@ -168,6 +177,7 @@ function AddVerticalChildrenDimension( scale: number ): void { const childrenId = `dim-x${xDim.toFixed(0)}-children-${container.properties.id}`; + const style = container.properties.dimensionOptions.childrenDimensions; const lastChildId = container.children[container.children.length - 1]; const lastChild = FindContainerById(containers, lastChildId); @@ -176,7 +186,10 @@ function AddVerticalChildrenDimension( return; } - let yChildrenStart = TransformY(lastChild.properties.y, lastChild.properties.height, lastChild.properties.positionReference); + let yChildrenStart = TransformY( + lastChild.properties.y, + lastChild.properties.height, + lastChild.properties.positionReference); let yChildrenEnd = yChildrenStart; // Find the min and max @@ -218,9 +231,9 @@ function AddVerticalChildrenDimension( xEnd: xDim, yStart: yChildrenStart + offset, yEnd: yChildrenEnd + offset, - strokeWidth: MODULE_STROKE_WIDTH, text: textChildren, - scale + scale, + style }); } @@ -234,6 +247,7 @@ function AddHorizontalBorrowerDimension( scale: number ): void { const it = MakeRecursionDFSIterator(container, containers, depth, currentTransform); + const style = container.properties.dimensionOptions.dimensionWithMarks; const marks = []; // list of vertical lines for the dimension for (const { container: childContainer, currentTransform: childCurrentTransform @@ -274,9 +288,9 @@ function AddHorizontalBorrowerDimension( xEnd: next, yStart: yDim, yEnd: yDim, - strokeWidth: MODULE_STROKE_WIDTH, text: value.toFixed(0), - scale + scale, + style }); count++; } @@ -293,6 +307,7 @@ function AddVerticalBorrowerDimension( scale: number ): void { const it = MakeRecursionDFSIterator(container, containers, depth, currentTransform); + const style = container.properties.dimensionOptions.dimensionWithMarks; const marks = []; // list of vertical lines for the dimension for (const { container: childContainer, currentTransform: childCurrentTransform @@ -338,9 +353,9 @@ function AddVerticalBorrowerDimension( xEnd: xDim, yStart: cur, yEnd: next, - strokeWidth: MODULE_STROKE_WIDTH, text: value.toFixed(0), - scale + scale, + style }); count++; } @@ -354,6 +369,7 @@ function AddVerticalSelfDimension( currentTransform: [number, number], scale: number ): void { + const style = container.properties.dimensionOptions.selfDimensions; const height = container.properties.height; const idVert = `dim-x${xDim.toFixed(0)}-${container.properties.id}`; let yStart = container.properties.y + currentTransform[1] + height; @@ -372,9 +388,9 @@ function AddVerticalSelfDimension( xEnd: xDim, yStart, yEnd, - strokeWidth: MODULE_STROKE_WIDTH, text: textVert, - scale + scale, + style }); } @@ -385,6 +401,7 @@ function AddHorizontalSelfDimension( currentTransform: [number, number], scale: number ): void { + const style = container.properties.dimensionOptions.selfDimensions; const width = container.properties.width; const id = `dim-y${yDim.toFixed(0)}-${container.properties.id}`; const xStart = container.properties.x + currentTransform[0]; @@ -398,8 +415,8 @@ function AddHorizontalSelfDimension( yStart: yDim, xEnd, yEnd: yDim, - strokeWidth: MODULE_STROKE_WIDTH, text, - scale + scale, + style }); } diff --git a/src/Components/Canvas/Renderer.ts b/src/Components/Canvas/Renderer.ts new file mode 100644 index 0000000..d325eed --- /dev/null +++ b/src/Components/Canvas/Renderer.ts @@ -0,0 +1,55 @@ +import { type IContainerModel } from '../../Interfaces/IContainerModel'; +import { type IHistoryState } from '../../Interfaces/IHistoryState'; +import { DIMENSION_MARGIN } from '../../utils/default'; +import { AddDimensions } from './DimensionLayer'; +import { RenderSymbol } from './Symbol'; + +export function RenderDimensions( + ctx: CanvasRenderingContext2D, + leftDim: number, + bottomDim: number, + topDim: number, + rightDim: number, + depth: number, + scale: number, + containers: Map, + container: IContainerModel, + currentTransform: [number, number] +): void { + ctx.save(); + const depthOffset = (DIMENSION_MARGIN * (depth + 1)) / scale; + const containerLeftDim = leftDim - depthOffset; + const containerTopDim = topDim - depthOffset; + const containerBottomDim = bottomDim + depthOffset; + const containerRightDim = rightDim + depthOffset; + const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim]; + AddDimensions(ctx, containers, container, dimMapped, currentTransform, scale, depth); + ctx.restore(); +} + +export function RenderSymbols( + current: IHistoryState, + ctx: CanvasRenderingContext2D, + scale: number +): void { + current.symbols.forEach((symbol) => { + RenderSymbol(symbol, ctx, scale); + }); +} + +export function RenderContainers( + ctx: CanvasRenderingContext2D, + container: IContainerModel, + x: number, + y: number +): void { + ctx.save(); + ctx.strokeStyle = container.properties.style?.stroke ?? '#000000'; + ctx.fillStyle = container.properties.style?.fill ?? '#000000'; + ctx.lineWidth = Number(container.properties.style?.strokeWidth ?? 1); + ctx.globalAlpha = Number(container.properties.style?.fillOpacity ?? 1); + ctx.fillRect(x, y, container.properties.width, container.properties.height); + ctx.globalAlpha = Number(container.properties.style?.strokeOpacity ?? 1); + ctx.strokeRect(x, y, container.properties.width, container.properties.height); + ctx.restore(); +} diff --git a/src/Components/Viewer/Viewer.tsx b/src/Components/Viewer/Viewer.tsx index a6092c4..5128b0d 100644 --- a/src/Components/Viewer/Viewer.tsx +++ b/src/Components/Viewer/Viewer.tsx @@ -2,16 +2,15 @@ import * as React from 'react'; import { type IContainerModel } from '../../Interfaces/IContainerModel'; import { type IHistoryState } from '../../Interfaces/IHistoryState'; import { type IPoint } from '../../Interfaces/IPoint'; -import { DIMENSION_MARGIN, USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default'; +import { USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default'; import { FindContainerById, MakeRecursionDFSIterator } from '../../utils/itertools'; import { BAR_WIDTH } from '../Bar/Bar'; import { Canvas } from '../Canvas/Canvas'; -import { AddDimensions } from '../Canvas/DimensionLayer'; import { RenderSelector } from '../Canvas/Selector'; import { SelectorMode, SVG } from '../SVG/SVG'; -import { RenderSymbol } from '../Canvas/Symbol'; import { useState } from 'react'; import { type ISymbolModel } from '../../Interfaces/ISymbolModel'; +import { RenderContainers, RenderDimensions, RenderSymbols } from '../Canvas/Renderer'; interface IViewerProps { className: string @@ -117,15 +116,14 @@ export function Viewer({ container, currentTransform ); - - // Draw selector - RenderSelector(ctx, frameCount, { - containers: current.containers, - scale, - selected: selectedContainer - }); } + // Draw selector + RenderSelector(ctx, frameCount, { + containers: current.containers, + scale, + selected: selectedContainer + }); // Draw symbols RenderSymbols(current, ctx, scale); ctx.restore(); @@ -158,47 +156,3 @@ export function Viewer({ ); } -function RenderSymbols( - current: IHistoryState, - ctx: CanvasRenderingContext2D, - scale: number -): void { - current.symbols.forEach((symbol) => { - RenderSymbol(symbol, ctx, scale); - }); -} - -function RenderDimensions( - ctx: CanvasRenderingContext2D, - leftDim: number, - bottomDim: number, - topDim: number, - rightDim: number, - depth: number, - scale: number, - containers: Map, - container: IContainerModel, - currentTransform: [number, number] -): void { - ctx.save(); - const depthOffset = (DIMENSION_MARGIN * (depth + 1)) / scale; - const containerLeftDim = leftDim - depthOffset; - const containerTopDim = topDim - depthOffset; - const containerBottomDim = bottomDim + depthOffset; - const containerRightDim = rightDim + depthOffset; - const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim]; - AddDimensions(ctx, containers, container, dimMapped, currentTransform, scale, depth); - ctx.restore(); -} - -function RenderContainers(ctx: CanvasRenderingContext2D, container: IContainerModel, x: number, y: number): void { - ctx.save(); - ctx.strokeStyle = container.properties.style?.stroke ?? '#000000'; - ctx.fillStyle = container.properties.style?.fill ?? '#000000'; - ctx.lineWidth = Number(container.properties.style?.strokeWidth ?? 1); - ctx.globalAlpha = Number(container.properties.style?.fillOpacity ?? 1); - ctx.fillRect(x, y, container.properties.width, container.properties.height); - ctx.globalAlpha = Number(container.properties.style?.strokeOpacity ?? 1); - ctx.strokeRect(x, y, container.properties.width, container.properties.height); - ctx.restore(); -}