Canvas: Add symbol dimension + Clean Viewer
This commit is contained in:
parent
5544eb05a4
commit
fe72768142
5 changed files with 154 additions and 47 deletions
18
src/Components/Canvas/Container.ts
Normal file
18
src/Components/Canvas/Container.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
|
|
||||||
|
export function RenderContainer(
|
||||||
|
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();
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
import { Orientation } from '../../Enums/Orientation';
|
import { Orientation } from '../../Enums/Orientation';
|
||||||
import { Position } from '../../Enums/Position';
|
import { Position } from '../../Enums/Position';
|
||||||
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
import { SHOW_SELF_DIMENSIONS, SHOW_BORROWER_DIMENSIONS, SHOW_CHILDREN_DIMENSIONS } from '../../utils/default';
|
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
||||||
|
import { SHOW_SELF_DIMENSIONS, SHOW_BORROWER_DIMENSIONS, SHOW_CHILDREN_DIMENSIONS, DIMENSION_MARGIN } from '../../utils/default';
|
||||||
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../utils/itertools';
|
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../utils/itertools';
|
||||||
import { TransformX, TransformY } from '../../utils/svg';
|
import { TransformX, TransformY } from '../../utils/svg';
|
||||||
|
import { type IDimensionStyle } from '../SVG/Elements/Dimension';
|
||||||
import { RenderDimension } from './Dimension';
|
import { RenderDimension } from './Dimension';
|
||||||
|
|
||||||
export function AddDimensions(
|
export function AddContainerDimensions(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
containers: Map<string, IContainerModel>,
|
containers: Map<string, IContainerModel>,
|
||||||
container: IContainerModel,
|
container: IContainerModel,
|
||||||
|
@ -66,6 +68,20 @@ export function AddDimensions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function AddSymbolDimensions(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
symbol: ISymbolModel,
|
||||||
|
scale: number,
|
||||||
|
depth: number
|
||||||
|
): void {
|
||||||
|
AddHorizontalSymbolDimension(
|
||||||
|
ctx,
|
||||||
|
symbol,
|
||||||
|
scale,
|
||||||
|
depth
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fonction that call another function given the positions
|
* Fonction that call another function given the positions
|
||||||
* @param dimMapped Position mapped depending on the Position enum in order:
|
* @param dimMapped Position mapped depending on the Position enum in order:
|
||||||
|
@ -420,3 +436,39 @@ function AddHorizontalSelfDimension(
|
||||||
style
|
style
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function AddHorizontalSymbolDimension(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
symbol: ISymbolModel,
|
||||||
|
scale: number,
|
||||||
|
depth: number
|
||||||
|
): void {
|
||||||
|
const width = symbol.x + (symbol.width / 2);
|
||||||
|
|
||||||
|
if (width == null || width <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = `dim-y-margin-left${symbol.width.toFixed(0)}-${symbol.id}`;
|
||||||
|
|
||||||
|
const offset = (DIMENSION_MARGIN * (depth + 1)) / scale;
|
||||||
|
const text = width
|
||||||
|
.toFixed(0)
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
// TODO: Put this in default.ts
|
||||||
|
const defaultDimensionSymbolStyle: IDimensionStyle = {
|
||||||
|
color: 'black'
|
||||||
|
};
|
||||||
|
|
||||||
|
RenderDimension(ctx, {
|
||||||
|
id,
|
||||||
|
xStart: 0,
|
||||||
|
yStart: -offset,
|
||||||
|
xEnd: width,
|
||||||
|
yEnd: -offset,
|
||||||
|
text,
|
||||||
|
scale,
|
||||||
|
style: defaultDimensionSymbolStyle
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,49 @@
|
||||||
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
||||||
|
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
|
||||||
import { DIMENSION_MARGIN } from '../../utils/default';
|
import { DIMENSION_MARGIN } from '../../utils/default';
|
||||||
import { AddDimensions } from './DimensionLayer';
|
import { MakeRecursionDFSIterator } from '../../utils/itertools';
|
||||||
|
import { RenderContainer } from './Container';
|
||||||
|
import { AddContainerDimensions, AddSymbolDimensions } from './DimensionLayer';
|
||||||
import { RenderSymbol } from './Symbol';
|
import { RenderSymbol } from './Symbol';
|
||||||
|
|
||||||
export function RenderDimensions(
|
export function RenderContainers(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
root: IContainerModel,
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
|
leftDim: number,
|
||||||
|
bottomDim: number,
|
||||||
|
topDim: number,
|
||||||
|
rightDim: number,
|
||||||
|
scale: number
|
||||||
|
): void {
|
||||||
|
const it = MakeRecursionDFSIterator(root, containers, 0, [0, 0]);
|
||||||
|
for (const { container, depth, currentTransform } of it) {
|
||||||
|
const [x, y] = [
|
||||||
|
container.properties.x + currentTransform[0],
|
||||||
|
container.properties.y + currentTransform[1]
|
||||||
|
];
|
||||||
|
|
||||||
|
// Draw container
|
||||||
|
RenderContainer(ctx, container, x, y);
|
||||||
|
|
||||||
|
// Draw dimensions
|
||||||
|
RenderContainerDimensions(
|
||||||
|
ctx,
|
||||||
|
leftDim,
|
||||||
|
bottomDim,
|
||||||
|
topDim,
|
||||||
|
rightDim,
|
||||||
|
depth,
|
||||||
|
scale,
|
||||||
|
containers,
|
||||||
|
container,
|
||||||
|
currentTransform
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RenderContainerDimensions(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
leftDim: number,
|
leftDim: number,
|
||||||
bottomDim: number,
|
bottomDim: number,
|
||||||
|
@ -23,33 +62,43 @@ export function RenderDimensions(
|
||||||
const containerBottomDim = bottomDim + depthOffset;
|
const containerBottomDim = bottomDim + depthOffset;
|
||||||
const containerRightDim = rightDim + depthOffset;
|
const containerRightDim = rightDim + depthOffset;
|
||||||
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
|
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
|
||||||
AddDimensions(ctx, containers, container, dimMapped, currentTransform, scale, depth);
|
AddContainerDimensions(ctx, containers, container, dimMapped, currentTransform, scale, depth);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RenderSymbols(
|
export function RenderSymbols(
|
||||||
current: IHistoryState,
|
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
|
current: IHistoryState,
|
||||||
scale: number
|
scale: number
|
||||||
): void {
|
): void {
|
||||||
current.symbols.forEach((symbol) => {
|
let count = 0;
|
||||||
RenderSymbol(symbol, ctx, scale);
|
current.symbols.forEach((symbol: ISymbolModel) => {
|
||||||
|
RenderSymbol(ctx, symbol, scale);
|
||||||
|
|
||||||
|
if (!symbol.showDimension) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSymbolDimensions(ctx, symbol, scale, count);
|
||||||
|
count++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RenderContainers(
|
export function RenderSymbolDimensions(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
|
depth: number,
|
||||||
|
scale: number,
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
container: IContainerModel,
|
container: IContainerModel,
|
||||||
x: number,
|
currentTransform: [number, number]
|
||||||
y: number
|
|
||||||
): void {
|
): void {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.strokeStyle = container.properties.style?.stroke ?? '#000000';
|
const depthOffset = (DIMENSION_MARGIN * (depth + 1)) / scale;
|
||||||
ctx.fillStyle = container.properties.style?.fill ?? '#000000';
|
const containerLeftDim = -depthOffset;
|
||||||
ctx.lineWidth = Number(container.properties.style?.strokeWidth ?? 1);
|
const containerTopDim = -depthOffset;
|
||||||
ctx.globalAlpha = Number(container.properties.style?.fillOpacity ?? 1);
|
const containerBottomDim = depthOffset;
|
||||||
ctx.fillRect(x, y, container.properties.width, container.properties.height);
|
const containerRightDim = depthOffset;
|
||||||
ctx.globalAlpha = Number(container.properties.style?.strokeOpacity ?? 1);
|
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
|
||||||
ctx.strokeRect(x, y, container.properties.width, container.properties.height);
|
AddContainerDimensions(ctx, containers, container, dimMapped, currentTransform, scale, depth);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { DIMENSION_MARGIN } from '../../utils/default';
|
||||||
const IMAGE_CACHE = new Map<string, HTMLImageElement>();
|
const IMAGE_CACHE = new Map<string, HTMLImageElement>();
|
||||||
|
|
||||||
export function RenderSymbol(
|
export function RenderSymbol(
|
||||||
symbol: ISymbolModel,
|
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
|
symbol: ISymbolModel,
|
||||||
scale: number): void {
|
scale: number): void {
|
||||||
const href = symbol.config.Image.Base64Image ?? symbol.config.Image.Url;
|
const href = symbol.config.Image.Base64Image ?? symbol.config.Image.Url;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ import { RenderSelector } from '../Canvas/Selector';
|
||||||
import { SelectorMode, SVG } from '../SVG/SVG';
|
import { SelectorMode, SVG } from '../SVG/SVG';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
||||||
import { RenderContainers, RenderDimensions, RenderSymbols } from '../Canvas/Renderer';
|
import { RenderContainers, RenderContainerDimensions, RenderSymbols } from '../Canvas/Renderer';
|
||||||
|
import { RenderContainer } from '../Canvas/Container';
|
||||||
|
|
||||||
interface IViewerProps {
|
interface IViewerProps {
|
||||||
className: string
|
className: string
|
||||||
|
@ -78,7 +79,12 @@ export function Viewer({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (USE_EXPERIMENTAL_CANVAS_API) {
|
if (USE_EXPERIMENTAL_CANVAS_API) {
|
||||||
function Draw(ctx: CanvasRenderingContext2D, frameCount: number, scale: number, translatePos: IPoint): void {
|
function Draw(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
frameCount: number,
|
||||||
|
scale: number,
|
||||||
|
translatePos: IPoint
|
||||||
|
): void {
|
||||||
if (mainContainer === undefined) {
|
if (mainContainer === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -93,30 +99,12 @@ export function Viewer({
|
||||||
ctx.setTransform(scale, 0, 0, scale, translatePos.x, translatePos.y);
|
ctx.setTransform(scale, 0, 0, scale, translatePos.x, translatePos.y);
|
||||||
ctx.fillStyle = '#000000';
|
ctx.fillStyle = '#000000';
|
||||||
|
|
||||||
const it = MakeRecursionDFSIterator(mainContainer, current.containers, 0, [0, 0]);
|
// Draw containers and symbol dimensions
|
||||||
for (const { container, depth, currentTransform } of it) {
|
RenderContainers(
|
||||||
const [x, y] = [
|
|
||||||
container.properties.x + currentTransform[0],
|
|
||||||
container.properties.y + currentTransform[1]
|
|
||||||
];
|
|
||||||
|
|
||||||
// Draw container
|
|
||||||
RenderContainers(ctx, container, x, y);
|
|
||||||
|
|
||||||
// Draw dimensions
|
|
||||||
RenderDimensions(
|
|
||||||
ctx,
|
ctx,
|
||||||
leftDim,
|
mainContainer,
|
||||||
bottomDim,
|
|
||||||
topDim,
|
|
||||||
rightDim,
|
|
||||||
depth,
|
|
||||||
scale,
|
|
||||||
current.containers,
|
current.containers,
|
||||||
container,
|
leftDim, bottomDim, topDim, rightDim, scale);
|
||||||
currentTransform
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw selector
|
// Draw selector
|
||||||
RenderSelector(ctx, frameCount, {
|
RenderSelector(ctx, frameCount, {
|
||||||
|
@ -124,8 +112,8 @@ export function Viewer({
|
||||||
scale,
|
scale,
|
||||||
selected: selectedContainer
|
selected: selectedContainer
|
||||||
});
|
});
|
||||||
// Draw symbols
|
// Draw symbols and symbol dimensions
|
||||||
RenderSymbols(current, ctx, scale);
|
RenderSymbols(ctx, current, scale);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue