Merged PR 200: Implement the Canvas API rather than using SVG

This commit is contained in:
Eric Nguyen 2022-10-02 19:20:19 +00:00
parent af1b32c8d6
commit 04d79688cb
6 changed files with 712 additions and 11 deletions

View file

@ -9,12 +9,17 @@ import { SaveEditorAsJSON, SaveEditorAsSVG } from './Actions/Save';
import { OnKey } from './Actions/Shortcuts';
import { events as EVENTS } from '../../Events/EditorEvents';
import { IEditorState } from '../../Interfaces/IEditorState';
import { DISABLE_API, MAX_HISTORY } from '../../utils/default';
import { DIMENSION_MARGIN, DISABLE_API, MAX_HISTORY, USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default';
import { AddSymbol, OnPropertyChange as OnSymbolPropertyChange, DeleteSymbol, SelectSymbol } from './Actions/SymbolOperations';
import { FindContainerById } from '../../utils/itertools';
import { FindContainerById, MakeRecursionDFSIterator } from '../../utils/itertools';
import { IMenuAction, Menu } from '../Menu/Menu';
import { GetAction } from './Actions/ContextMenuActions';
import { AddContainerToSelectedContainer, AddContainer } from './Actions/AddContainer';
import { Canvas } from '../Canvas/Canvas';
import { BAR_WIDTH } from '../Bar/Bar';
import { IPoint } from '../../Interfaces/IPoint';
import { AddDimensions } from '../Canvas/DimensionLayer';
import { RenderSelector } from '../Canvas/Selector';
interface IEditorProps {
root: Element | Document
@ -228,6 +233,55 @@ export function Editor(props: IEditorProps): JSX.Element {
const configuration = props.configuration;
const current = GetCurrentHistoryState(history, historyCurrentStep);
const selected = FindContainerById(current.mainContainer, current.selectedContainerId);
function Draw(ctx: CanvasRenderingContext2D, frameCount: number, scale: number, translatePos: IPoint): void {
const topDim = current.mainContainer.properties.y;
const leftDim = current.mainContainer.properties.x;
const rightDim = current.mainContainer.properties.x + current.mainContainer.properties.width;
const bottomDim = current.mainContainer.properties.y + current.mainContainer.properties.height;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
ctx.translate(translatePos.x, translatePos.y);
ctx.scale(scale, scale);
ctx.fillStyle = '#000000';
const it = MakeRecursionDFSIterator(current.mainContainer, 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
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';
// 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);
// Draw selector
RenderSelector(ctx, frameCount, {
scale,
selected
});
}
ctx.restore();
}
return (
<div ref={editorRef} className="Editor font-sans h-full">
<UI
@ -310,15 +364,26 @@ export function Editor(props: IEditorProps): JSX.Element {
configuration
)}
saveEditorAsSVG={() => SaveEditorAsSVG()}
loadState={(move) => setHistoryCurrentStep(move)} />
<SVG
width={current.mainContainer?.properties.width}
height={current.mainContainer?.properties.height}
selected={selected}
symbols={current.symbols}
>
{current.mainContainer}
</SVG>
loadState={(move) => setHistoryCurrentStep(move)}
/>
{
USE_EXPERIMENTAL_CANVAS_API
? <Canvas
draw={Draw}
className='ml-16'
width={window.innerWidth - BAR_WIDTH}
height={window.innerHeight}
/>
: <SVG
width={current.mainContainer?.properties.width}
height={current.mainContainer?.properties.height}
selected={selected}
symbols={current.symbols}
>
{current.mainContainer}
</SVG>
}
<Menu
getListener={() => editorRef.current}
actions={menuActions}