Merged PR 209: Implement Symbols in Canvas mode
This commit is contained in:
parent
ec7ee7891e
commit
2cb851866b
4 changed files with 107 additions and 22 deletions
|
@ -70,12 +70,11 @@ function UseCanvas(draw: (context: CanvasRenderingContext2D, frameCount: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(context, frameCount.current, scale.current, translatePos.current);
|
draw(context, frameCount.current, scale.current, translatePos.current);
|
||||||
evt.preventDefault();
|
|
||||||
}
|
}
|
||||||
canvas.addEventListener('mousedown', MouseDown);
|
canvas.addEventListener('mousedown', MouseDown);
|
||||||
window.addEventListener('mouseup', MouseUp);
|
window.addEventListener('mouseup', MouseUp);
|
||||||
canvas.addEventListener('mousemove', MouseMove);
|
canvas.addEventListener('mousemove', MouseMove);
|
||||||
canvas.addEventListener('wheel', HandleScroll);
|
canvas.addEventListener('wheel', HandleScroll, { passive: true });
|
||||||
|
|
||||||
function Render(): void {
|
function Render(): void {
|
||||||
if (context === null) {
|
if (context === null) {
|
||||||
|
|
45
src/Components/Canvas/Symbol.ts
Normal file
45
src/Components/Canvas/Symbol.ts
Normal 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();
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import { Canvas } from '../Canvas/Canvas';
|
||||||
import { AddDimensions } from '../Canvas/DimensionLayer';
|
import { AddDimensions } from '../Canvas/DimensionLayer';
|
||||||
import { RenderSelector } from '../Canvas/Selector';
|
import { RenderSelector } from '../Canvas/Selector';
|
||||||
import { SVG } from '../SVG/SVG';
|
import { SVG } from '../SVG/SVG';
|
||||||
|
import { RenderSymbol } from '../Canvas/Symbol';
|
||||||
|
|
||||||
interface IViewerProps {
|
interface IViewerProps {
|
||||||
isLeftSidebarOpen: boolean
|
isLeftSidebarOpen: boolean
|
||||||
|
@ -107,9 +108,9 @@ export function Viewer({
|
||||||
|
|
||||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.translate(translatePos.x, translatePos.y);
|
ctx.setTransform(scale, 0, 0, scale, translatePos.x, translatePos.y);
|
||||||
ctx.scale(scale, scale);
|
|
||||||
ctx.fillStyle = '#000000';
|
ctx.fillStyle = '#000000';
|
||||||
|
|
||||||
const it = MakeRecursionDFSIterator(current.mainContainer, 0, [0, 0]);
|
const it = MakeRecursionDFSIterator(current.mainContainer, 0, [0, 0]);
|
||||||
for (const { container, depth, currentTransform } of it) {
|
for (const { container, depth, currentTransform } of it) {
|
||||||
const [x, y] = [
|
const [x, y] = [
|
||||||
|
@ -118,25 +119,20 @@ export function Viewer({
|
||||||
];
|
];
|
||||||
|
|
||||||
// Draw container
|
// Draw container
|
||||||
ctx.strokeStyle = container.properties.style?.stroke ?? '#000000';
|
RenderContainers(ctx, container, x, y);
|
||||||
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';
|
|
||||||
|
|
||||||
// Draw dimensions
|
// Draw dimensions
|
||||||
const containerLeftDim = leftDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
|
RenderDimensions(
|
||||||
const containerTopDim = topDim - (DIMENSION_MARGIN * (depth + 1)) / scale;
|
ctx,
|
||||||
const containerBottomDim = bottomDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
|
leftDim,
|
||||||
const containerRightDim = rightDim + (DIMENSION_MARGIN * (depth + 1)) / scale;
|
bottomDim,
|
||||||
const dimMapped = [containerLeftDim, containerBottomDim, containerTopDim, containerRightDim];
|
topDim,
|
||||||
AddDimensions(ctx, container, dimMapped, currentTransform, scale, depth);
|
rightDim,
|
||||||
|
depth,
|
||||||
|
scale,
|
||||||
|
container,
|
||||||
|
currentTransform
|
||||||
|
);
|
||||||
|
|
||||||
// Draw selector
|
// Draw selector
|
||||||
RenderSelector(ctx, frameCount, {
|
RenderSelector(ctx, frameCount, {
|
||||||
|
@ -144,6 +140,9 @@ export function Viewer({
|
||||||
selected: selectedContainer
|
selected: selectedContainer
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw symbols
|
||||||
|
RenderSymbols(current, ctx, scale);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -171,3 +170,45 @@ export function Viewer({
|
||||||
</SVG>
|
</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();
|
||||||
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ export const MAX_HISTORY = 200;
|
||||||
export const APPLY_BEHAVIORS_ON_CHILDREN = true;
|
export const APPLY_BEHAVIORS_ON_CHILDREN = true;
|
||||||
|
|
||||||
/** Framerate of the svg controller (recommanded = 60) */
|
/** Framerate of the svg controller (recommanded = 60) */
|
||||||
export const MAX_FRAMERATE = 60;
|
export const MAX_FRAMERATE = 120;
|
||||||
|
|
||||||
/// CONTAINER DEFAULTS ///
|
/// CONTAINER DEFAULTS ///
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue