Canvas: Implement dimension style

This commit is contained in:
Eric NGUYEN 2023-02-17 15:09:48 +01:00
parent 5b367f8e57
commit 5544eb05a4
5 changed files with 117 additions and 80 deletions

View file

@ -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<HTMLCanvasElement> {
function UseCanvas(
draw: (context: CanvasRenderingContext2D,
frameCount: number,
scale: number,
translatePos: IPoint) => void
): React.RefObject<HTMLCanvasElement> {
const canvasRef = useRef<HTMLCanvasElement>(null);
const frameCount = useRef(0);
const translatePos = useRef({

View file

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

View file

@ -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<string, IContainerModel>,
@ -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
});
}

View file

@ -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<string, IContainerModel>,
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();
}

View file

@ -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,6 +116,7 @@ export function Viewer({
container,
currentTransform
);
}
// Draw selector
RenderSelector(ctx, frameCount, {
@ -124,8 +124,6 @@ export function Viewer({
scale,
selected: selectedContainer
});
}
// Draw symbols
RenderSymbols(current, ctx, scale);
ctx.restore();
@ -158,47 +156,3 @@ export function Viewer({
</SVG>
);
}
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<string, IContainerModel>,
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();
}