Skip to content

Commit

Permalink
Fix <Group>
Browse files Browse the repository at this point in the history
  • Loading branch information
TooTallNate committed Jan 31, 2024
1 parent 5e0f32c commit a034fdf
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 160 deletions.
4 changes: 2 additions & 2 deletions src/event-target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class TelaEventTarget extends EventTarget {
PATCHED_EVENT.add(event);
}

const rtn = super.dispatchEvent(event);

// If there's an `on${type}` prop set, invoke that handler
const prop = `on${event.type}`;
const fn = (this as any)[prop];
Expand All @@ -28,8 +30,6 @@ export class TelaEventTarget extends EventTarget {
}
}

const rtn = super.dispatchEvent(event);

// Ensure `cancelBubble` is set to true if `stopPropagation()` was called
if (!event.cancelBubble && STOP_PROPAGATION.has(event)) {
Object.defineProperty(event, 'cancelBubble', {
Expand Down
131 changes: 131 additions & 0 deletions src/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import type { Root } from './root';
import type { Entity } from './entity';
import type { ICanvas, Point, TelaMouseEvent } from './types';
import { findTarget, getLayer, cloneMouseEvent } from './util';

function scaledCoordinates(canvas: ICanvas, x: number, y: number): Point {
// Get CSS size
const cssWidth = canvas.clientWidth ?? canvas.width;
const cssHeight = canvas.clientHeight ?? canvas.height;

// Get drawing buffer size
const bufferWidth = canvas.width;
const bufferHeight = canvas.height;

// Calculate the ratio
const widthRatio = bufferWidth / cssWidth;
const heightRatio = bufferHeight / cssHeight;

return { x: x * widthRatio, y: y * heightRatio };
}

export function proxyEvents(
canvasOrGroup: EventTarget,
root: Root,
scaleCoordinates: boolean,
) {
let mouseCurrentlyOver: Root | Entity | null = null;

//canvasOrGroup.addEventListener?.('touchstart', (_event) => {
// const event = _event as TouchEvent;
// console.log(event);
// _event.preventDefault();
// const { x, y } = scaleCoordinates ? scaledCoordinates(
// canvasOrGroup,
// event.layerX,
// event.layerY,
// );
// let target: EventTarget = root;
// for (let i = root.entities.length - 1; i >= 0; i--) {
// const entity = root.entities[i];
// if (entity.isPointInPath(x, y)) {
// target = entity;
// break;
// }
// }
//});

function doMouseEvent(_event: Event) {
const event = _event as TelaMouseEvent;
const point = scaledCoordinates(
canvasOrGroup as ICanvas,
event.layerX,
event.layerY,
);
const target = findTarget(root, point);
const layer = getLayer(target, point);
const ev = cloneMouseEvent(event, point, layer);
target.dispatchEvent(ev);
if (ev.defaultPrevented) {
event.preventDefault();
}
if (ev.cancelBubble) {
event.stopPropagation();
}
return target;
}
canvasOrGroup.addEventListener?.('click', doMouseEvent);
canvasOrGroup.addEventListener?.('mousedown', doMouseEvent);
canvasOrGroup.addEventListener?.('mouseup', doMouseEvent);
canvasOrGroup.addEventListener?.('mousemove', (e) => {
const event = e as TelaMouseEvent;
const point = scaledCoordinates(
canvasOrGroup as ICanvas,
event.layerX,
event.layerY,
);
const target = findTarget(root, point);
//console.log(point, target);
const layer = getLayer(target, point);

if (target !== mouseCurrentlyOver) {
if (mouseCurrentlyOver) {
// do "mouseleave" event
mouseCurrentlyOver.dispatchEvent(
cloneMouseEvent(
event,
point,
getLayer(mouseCurrentlyOver, point),
'mouseleave',
{
bubbles: false,
cancelable: false,
},
),
);
}

mouseCurrentlyOver = target;
//console.log(target);

// do "mouseenter" event
target.dispatchEvent(
cloneMouseEvent(event, point, layer, 'mouseenter', {
bubbles: false,
cancelable: false,
}),
);
}

const ev = cloneMouseEvent(event, point, layer);
target.dispatchEvent(ev);
if (ev.defaultPrevented) {
event.preventDefault();
}
if (ev.cancelBubble) {
event.stopPropagation();
}
return target;
});
canvasOrGroup.addEventListener?.('mouseleave', (_e) => {
mouseCurrentlyOver = null;
const event = _e as TelaMouseEvent;
const point = scaledCoordinates(
canvasOrGroup as ICanvas,
event.layerX,
event.layerY,
);
const ev = cloneMouseEvent(_e as TelaMouseEvent, point, point);
root.dispatchEvent(ev);
});
}
23 changes: 17 additions & 6 deletions src/group.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import { Root, RootParams } from './root';
import { Entity, EntityProps } from './entity';
import { Root } from './root';
import type { ICanvas, ICanvasRenderingContext2D } from './types';
import { findTarget, getLayer } from './util';
import { proxyEvents } from './events';

export interface GroupProps extends EntityProps {}

export class Group extends Entity {
subroot: Root;
subcanvas: ICanvas;

constructor(opts: GroupProps) {
constructor(opts: GroupProps, root: Root) {
super(opts);
this.subcanvas = new OffscreenCanvas(
this.subcanvas = root.createCanvas(
this.calculatedWidth,
this.calculatedHeight,
);
this.subroot = new GroupRoot(this.subcanvas.getContext('2d')!, this);
const ctx = this.subcanvas.getContext('2d');
if (!ctx) {
throw new Error();
}
this.subroot = new GroupRoot(ctx, this, root);
proxyEvents(this, this.subroot, false);
}

render(): void {
Expand All @@ -33,8 +40,12 @@ export class Group extends Entity {
class GroupRoot extends Root {
#group: Group;

constructor(ctx: ICanvasRenderingContext2D, group: Group) {
super(ctx);
constructor(
ctx: ICanvasRenderingContext2D,
group: Group,
opts: RootParams,
) {
super(ctx, opts);
this.#group = group;
}

Expand Down
5 changes: 0 additions & 5 deletions src/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ export class Image extends Entity {
render(): void {
super.render();
let { image, root } = this;
if (!root) {
throw new Error(
`${this.constructor.name} instance has not been added to a root context`,
);
}
if (!image) {
image = this.image = new root.Image();
image.onload = this.#onload.bind(this);
Expand Down
30 changes: 13 additions & 17 deletions src/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,30 @@ import { Shape, type ShapeProps } from './shape.js';
import { IPath2D } from './types.js';

export type PathProps = ShapeProps & {
width: number;
height: number;
d: string;
};

export class Path extends Shape {
#d!: string;
#path!: IPath2D;
d: string;
#path?: IPath2D;

constructor(opts: PathProps) {
super(opts);
this.d = opts.d;
}

get d() {
return this.#d;
}

set d(v: string) {
const parsed: [string, ...number[]][] = parseSvgPath(v);
let modified = parsed
.map((c) => `${c[0]}${c.slice(1).join(',')}`)
.join('');
// TODO: map absolute coordinates to relative
//console.log({ parsed, v, modified });
this.#d = modified;
this.#path = new this.root.Path2D(modified);
}

get path() {
if (!this.#path) {
const parsed: [string, ...number[]][] = parseSvgPath(this.d);
let modified = parsed
.map((c) => `${c[0]}${c.slice(1).join(',')}`)
.join('');
// TODO: map absolute coordinates to relative
//console.log({ parsed, v, modified });
this.#path = new this.root.Path2D(modified);
}
return this.#path;
}
}
Loading

0 comments on commit a034fdf

Please sign in to comment.