Skip to content

Commit

Permalink
More improvements.
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastianStehle committed Nov 16, 2024
1 parent 5219170 commit 7339a7d
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 80 deletions.
12 changes: 11 additions & 1 deletion .storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import '@app/index.scss'

export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
actions: {
argTypesRegex: '^on[A-Z].*'
},
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},

backgrounds: {
values: [
{ name: 'Dark', value: '#333' },
{ name: 'Light', value: '#F7F9F2' },
{ name: 'Gray', value: '#efefef' },
]
}
}
2 changes: 1 addition & 1 deletion src/core/react/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const CanvasComponent = React.memo((props: SizeMeProps & CanvasProps) => {
minY: round(-transform.y / zoom),
maxX: round(w / zoom),
maxY: round(h / zoom),
zoom: round(zoom),
zoom: zoom,
};
}, [transform, size]);

Expand Down
2 changes: 1 addition & 1 deletion src/wireframes/engine/canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Engine } from './interface';

export interface CanvasProps {
// The optional viewbox.
viewBox: ViewBox;
viewBox?: ViewBox;

// The class name.
className?: string;
Expand Down
100 changes: 76 additions & 24 deletions src/wireframes/engine/elements.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@
import { Meta } from '@storybook/react';
import { Card, Col, Row } from 'antd';
import * as React from 'react';
import { Canvas, ViewBox } from '@app/core';
import { CanvasProps } from './canvas';
import { Engine, EngineObject, Listener } from './interface';
import { PixiCanvasView } from './pixi/canvas/PixiCanvas';
import { SvgCanvasView } from './svg/canvas/SvgCanvas';

const VIEWBOX = { minX: 0, minY: 0, maxX: 500, maxY: 500, zoom: 1 };

interface EngineProps {
// The viewbox.
viewBox?: ViewBox;

// The render function.
onRender: (engine: Engine) => void;
}

const Canvas = (props: EngineProps & { canvasView: React.ComponentType<CanvasProps> }) => {
const EngineCanvas = (props: EngineProps & { canvasView: React.ComponentType<CanvasProps> }) => {
const [engine, setEngine] = React.useState<Engine>();
const { onRender } = props;

Expand All @@ -31,23 +33,46 @@ const Canvas = (props: EngineProps & { canvasView: React.ComponentType<CanvasPro
}, [engine, onRender]);

return (
<div style={{ lineHeight: 0 }}>
<props.canvasView style={{ height: '500px', width: '500px' }} viewBox={VIEWBOX} onInit={setEngine} />
<div style={{ height: '500px', overflow: 'hidden' }}>
<props.canvasView style={{ height: '500px', overflow: 'hidden' }} viewBox={props.viewBox} onInit={setEngine} />
</div>
);
};

const CompareView = (props: EngineProps) => {
const CompareView = (props: Omit<EngineProps, 'viewBox'>) => {
return (
<Row gutter={8}>
<Row gutter={16}>
<Col span={12}>
<Card title='SVG' style={{ overflow: 'hidden' }}>
<Canvas canvasView={SvgCanvasView} {...props} />
<EngineCanvas canvasView={SvgCanvasView} {...props} />
</Card>
</Col>
<Col span={12}>
<Card title='PIXI' style={{ overflow: 'hidden' }}>
<Canvas canvasView={PixiCanvasView} {...props} />
<EngineCanvas canvasView={PixiCanvasView as any} {...props} />
</Card>
</Col>
</Row>
);
};

const CompareCanvasViews = (props: Omit<EngineProps, 'viewBox'>) => {
return (
<Row gutter={16}>
<Col span={12}>
<Card title='SVG'>
<Canvas padding={0} contentWidth={500} contentHeight={500}
onRender={viewBox =>
<EngineCanvas viewBox={viewBox} canvasView={SvgCanvasView} {...props} />
} />
</Card>
</Col>
<Col span={12}>
<Card title='PIXI'>
<Canvas padding={0} contentWidth={500} contentHeight={500}
onRender={viewBox =>
<EngineCanvas viewBox={viewBox} canvasView={PixiCanvasView as any} {...props} />
} />
</Card>
</Col>
</Row>
Expand Down Expand Up @@ -97,26 +122,30 @@ const HitTestForCanvas = (props: { canvasView: React.ComponentType<CanvasProps>
}, [engine]);

return (

<div style={{ lineHeight: 1.5 }}>
Hits: {hits?.length}, X: {relativeX}, Y: {relativeY}

<props.canvasView style={{ height: '500px', width: '500px' }} viewBox={VIEWBOX} onInit={setEngine} />
<div style={{ height: '500px', overflow: 'hidden' }}>
<Canvas padding={0} contentWidth={500} contentHeight={500}
onRender={viewBox =>
<props.canvasView viewBox={viewBox} style={{ height: '500px' }} onInit={setEngine} />
} />
</div>
</div>
);
};

const HitTest = () => {
const CompareHitTests = () => {
return (
<Row gutter={8}>
<Row gutter={16}>
<Col span={12}>
<Card title='SVG' style={{ overflow: 'hidden' }}>
<HitTestForCanvas canvasView={SvgCanvasView} />
</Card>
</Col>
<Col span={12}>
<Card title='PIXI' style={{ overflow: 'hidden' }}>
<HitTestForCanvas canvasView={PixiCanvasView} />
<HitTestForCanvas canvasView={PixiCanvasView as any} />
</Card>
</Col>
</Row>
Expand All @@ -135,7 +164,30 @@ export default {

export const Hits = () => {
return (
<HitTest />
<CompareHitTests />
);
};

export const Pan = () => {
return (
<CompareCanvasViews
onRender={(engine) => {
const layer = engine.layer('layer1');

const rect = layer.rect();
rect.fill('blue');
rect.strokeColor('red');
rect.strokeWidth(2);
rect.plot({ x: 200, y: 250, w: 200, h: 100 });

const text = layer.text();
text.color('white');
text.fill('black');
text.fontFamily('Arial');
text.fontSize(16);
text.text('Hello Engine');
text.plot({ x: 50, y: 100, w: 200, h: 60, padding: 5 });
}} />
);
};

Expand Down Expand Up @@ -202,16 +254,16 @@ export const Text = () => {
const text1 = layer.text();
text1.color('white');
text1.fill('black');
text1.fontFamily('inherit');
text1.fontSize('16px');
text1.fontFamily('Arial');
text1.fontSize(16);
text1.text('Hello Engine');
text1.plot({ x: 50, y: 100, w: 200, h: 60, padding: 8 });
text1.plot({ x: 50, y: 100, w: 200, h: 60, padding: 0 });

const text2 = layer.text();
text2.color('white');
text2.fill('red');
text2.fontFamily('inherit');
text2.fontSize('16px');
text2.fontFamily('Arial');
text2.fontSize(16);
text2.text('Hello Engine');
text2.plot({ x: 50, y: 200, w: 200, h: 60, padding: 8 });
}}
Expand Down Expand Up @@ -259,17 +311,17 @@ export const Cursors = () => {
move.color('white');
move.cursor('move');
move.fill('black');
move.fontFamily('inherit');
move.fontSize('16px');
move.fontFamily('Arial');
move.fontSize(16);
move.text('move');
move.plot({ x: 50, y: 100, w: 200, h: 60, padding: 20 });

const resize = layer.text();
resize.color('white');
resize.cursor('n-resize');
resize.fill('red');
resize.fontFamily('inherit');
resize.fontSize('16px');
resize.fontFamily('Arial');
resize.fontSize(16);
resize.text('resize');
resize.plot({ x: 50, y: 200, w: 200, h: 60, padding: 20 });
}}
Expand Down
4 changes: 2 additions & 2 deletions src/wireframes/engine/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export interface EngineLayer {
hide(): void;

// Makes a hit and returns matching elements.
hitTest(clientX: number, clientY: number): EngineObject[];
hitTest(x: number, y: number): EngineObject[];
}

export type EngineRectOrEllipsePlotArgs = { x: number; y: number; w: number; h: number; rotation?: number; rx?: number; ry?: number };
Expand Down Expand Up @@ -125,7 +125,7 @@ export interface EngineText extends EngineObject {
fill(value: string): void;

// Sets the font size.
fontSize(value: string): void;
fontSize(value: number): void;

// Sets the font family.
fontFamily(value: string): void;
Expand Down
30 changes: 27 additions & 3 deletions src/wireframes/engine/pixi/canvas/PixiCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { Application } from 'pixi.js';
import * as React from 'react';
import { SizeMeProps, withSize } from 'react-sizeme';
import { ViewBox } from '@app/core';
import { PixiEngine } from './../engine';

Expand All @@ -24,11 +25,12 @@ export interface PixiCanvasProps {
onInit: (engine: PixiEngine) => any;
}

export const PixiCanvasView = (props: PixiCanvasProps) => {
const PixiCanvasViewComponent = (props: PixiCanvasProps & SizeMeProps) => {
const {
className,
onInit,
style,
viewBox,
} = props;

const [engine, setEngine] = React.useState<PixiEngine>();
Expand Down Expand Up @@ -69,12 +71,34 @@ export const PixiCanvasView = (props: PixiCanvasProps) => {
}, []);

React.useEffect(() => {
if (engine && onInit) {
onInit(engine);
if (!engine || !onInit) {
return;
}

onInit(engine);
}, [engine, onInit]);

React.useEffect(() => {
if (!engine) {
return;
}

const root = engine.application.stage;
if (viewBox) {
root.scale = viewBox.zoom;
root.x = -viewBox.minX * viewBox.zoom;
root.y = -viewBox.minY * viewBox.zoom;
} else {
root.scale = 1;
root.x = 0;
root.y = 0;
}

}, [engine, viewBox]);

return (
<div style={style} className={className} ref={doInit} />
);
};

export const PixiCanvasView = withSize({ monitorWidth: true, monitorHeight: true })(PixiCanvasViewComponent);
18 changes: 12 additions & 6 deletions src/wireframes/engine/pixi/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class PixiEngine implements Engine {
private isDragging = false;

constructor(
private readonly application: Application,
public readonly application: Application,
) {
application.stage.eventMode = 'static';

Expand Down Expand Up @@ -114,10 +114,8 @@ export class PixiEngine implements Engine {
private buildHitEvent = (event: MouseEvent): EngineHitEvent => {
const boundary = new EventBoundary(this.application.stage);

const bounds = this.application.canvas.getBoundingClientRect();
const relativeX = event.clientX - bounds.x;
const relativeY = event.clientY - bounds.y;
const hit = boundary.hitTest(relativeX, relativeY);
const { x, y } = this.getPosition(event);
const hit = boundary.hitTest(y, y);

let currentTarget: Container = hit;
let eventObject: EngineObject | null = null;
Expand All @@ -140,7 +138,7 @@ export class PixiEngine implements Engine {
const engineEvent =
new EngineHitEvent(
event,
new Vec2(relativeX, relativeY),
new Vec2(x, y),
eventObject,
eventItem,
hit);
Expand Down Expand Up @@ -187,6 +185,14 @@ export class PixiEngine implements Engine {
document.body.style.cursor = 'default';
};

private getPosition(event: MouseEvent) {
const bounds = this.application.canvas.getBoundingClientRect();
const x = event.clientX - bounds.x;
const y = event.clientY - bounds.y;

return this.application.stage.worldTransform.applyInverse({ x, y });
}

private handleMouseDown() {
this.isDragging = true;
}
Expand Down
7 changes: 6 additions & 1 deletion src/wireframes/engine/pixi/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,13 @@ export class PixiLayer implements EngineLayer {
this.container.removeFromParent();
}

public hitTest(clientX: number, clientY: number): EngineObject[] {
public hitTest(x: number, y: number): EngineObject[] {
const boundary = new EventBoundary(this.container);

const {
x: clientX,
y: clientY,
} = this.application.stage.worldTransform.apply({ x, y });

const hit = boundary.hitTest(clientX, clientY);
if (!hit) {
Expand Down
1 change: 1 addition & 0 deletions src/wireframes/engine/pixi/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ const FACTORY_TEXT = (_: Properties, existing?: HTMLText) => {

const mask = new Graphics();
existing.mask = mask;
existing.resolution = 4;
existing.addChild(mask);
}

Expand Down
Loading

0 comments on commit 7339a7d

Please sign in to comment.