Merged PR 209: Implement Symbols in Canvas mode

This commit is contained in:
Eric Nguyen 2022-10-04 13:25:07 +00:00
parent ec7ee7891e
commit 2cb851866b
4 changed files with 107 additions and 22 deletions

View file

@ -70,12 +70,11 @@ function UseCanvas(draw: (context: CanvasRenderingContext2D, frameCount: number,
}
draw(context, frameCount.current, scale.current, translatePos.current);
evt.preventDefault();
}
canvas.addEventListener('mousedown', MouseDown);
window.addEventListener('mouseup', MouseUp);
canvas.addEventListener('mousemove', MouseMove);
canvas.addEventListener('wheel', HandleScroll);
canvas.addEventListener('wheel', HandleScroll, { passive: true });
function Render(): void {
if (context === null) {

View file

@ -0,0 +1,45 @@
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { DIMENSION_MARGIN } from '../../utils/default';
const IMAGE_CACHE = new Map<string, HTMLImageElement>();
export function RenderSymbol(
symbol: ISymbolModel,
ctx: CanvasRenderingContext2D,
scale: number): void {
const href = symbol.config.Image.Base64Image ?? symbol.config.Image.Url;
if (href === undefined) {
return;
}
const image: HTMLImageElement | undefined = IMAGE_CACHE.get(href);
if (image === undefined) {
const newImage = new Image();
newImage.src = href;
IMAGE_CACHE.set(href, newImage);
newImage.onload = () => {
DrawImage(ctx, scale, newImage, symbol);
};
return;
}
DrawImage(ctx, scale, image, symbol);
}
function DrawImage(
ctx: CanvasRenderingContext2D,
scale: number,
image: HTMLImageElement,
symbol: ISymbolModel
): void {
ctx.save();
ctx.fillStyle = '#000000';
ctx.drawImage(
image,
symbol.x,
-DIMENSION_MARGIN,
symbol.width,
symbol.height
);
ctx.restore();
}

View file

@ -9,6 +9,7 @@ import { Canvas } from '../Canvas/Canvas';
import { AddDimensions } from '../Canvas/DimensionLayer';
import { RenderSelector } from '../Canvas/Selector';
import { SVG } from '../SVG/SVG';
import { RenderSymbol } from '../Canvas/Symbol';
interface IViewerProps {
isLeftSidebarOpen: boolean
@ -107,9 +108,9 @@ export function Viewer({
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
ctx.translate(translatePos.x, translatePos.y);
ctx.scale(scale, scale);
ctx.setTransform(scale, 0, 0, scale, translatePos.x, translatePos.y);
ctx.fillStyle = '#000000';
const it = MakeRecursionDFSIterator(current.mainContainer, 0, [0, 0]);
for (const { container, depth, currentTransform } of it) {
const [x, y] = [
@ -118,25 +119,20 @@ export function Viewer({
];
// Draw container
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.globalAlpha = 1;
ctx.lineWidth = 1;
ctx.fillStyle = '#000000';
ctx.strokeStyle = '#000000';
RenderContainers(ctx, container, x, y);
// Draw dimensions
const containerLeftDim = leftDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerTopDim = topDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerBottomDim = bottomDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerRightDim = rightDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
AddDimensions(ctx, container, dimMapped, currentTransform, scale, depth);
RenderDimensions(
ctx,
leftDim,
bottomDim,
topDim,
rightDim,
depth,
scale,
container,
currentTransform
);
// Draw selector
RenderSelector(ctx, frameCount, {
@ -144,6 +140,9 @@ export function Viewer({
selected: selectedContainer
});
}
// Draw symbols
RenderSymbols(current, ctx, scale);
ctx.restore();
}
return (
@ -171,3 +170,45 @@ 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,
container: IContainerModel,
currentTransform: [number, number]
): void {
ctx.save();
const containerLeftDim = leftDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerTopDim = topDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerBottomDim = bottomDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
const containerRightDim = rightDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
AddDimensions(ctx, 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();
}

View file

@ -33,7 +33,7 @@ export const MAX_HISTORY = 200;
export const APPLY_BEHAVIORS_ON_CHILDREN = true;
/** Framerate of the svg controller (recommanded = 60) */
export const MAX_FRAMERATE = 60;
export const MAX_FRAMERATE = 120;
/// CONTAINER DEFAULTS ///