Skip to content

Commit

Permalink
feat(rdom-canvas): add lifecycle events, canvas opts
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Oct 23, 2021
1 parent 0899aed commit a579904
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
4 changes: 2 additions & 2 deletions packages/rdom-canvas/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"dependencies": {
"@thi.ng/adapt-dpi": "^2.0.3",
"@thi.ng/api": "^8.0.3",
"@thi.ng/associative": "^6.0.3",
"@thi.ng/checks": "^3.0.3",
"@thi.ng/hiccup-canvas": "^2.0.4",
"@thi.ng/rdom": "^0.7.3",
Expand Down Expand Up @@ -83,6 +84,5 @@
],
"status": "alpha",
"year": 2020
},
"gitHead": "3c5f903104da150588946a94bb118ad559ad395d"
}
}
52 changes: 45 additions & 7 deletions packages/rdom-canvas/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { adaptDPI } from "@thi.ng/adapt-dpi";
import type { IToHiccup } from "@thi.ng/api";
import type { Fn, Fn2, Fn3, IToHiccup } from "@thi.ng/api";
import { withoutKeysObj } from "@thi.ng/associative/without-keys";
import { implementsFunction } from "@thi.ng/checks/implements-function";
import { resolveColor } from "@thi.ng/hiccup-canvas/color";
import { draw } from "@thi.ng/hiccup-canvas/draw";
import type { IComponent, IMountWithState, NumOrElement } from "@thi.ng/rdom";
import { Component } from "@thi.ng/rdom/component";
Expand All @@ -10,6 +12,26 @@ import { isSubscribable } from "@thi.ng/rstream/checks";
import { reactive } from "@thi.ng/rstream/stream";
import { sideEffect } from "@thi.ng/transducers/side-effect";

export interface CanvasOpts {
/**
* Custom component lifecycle handler called when canvas first mounts.
*/
onmount: Fn2<HTMLCanvasElement, CanvasRenderingContext2D, void>;
/**
* Custom component lifecycle handler called when canvas unmounts.
*/
onunmount: Fn<HTMLCanvasElement, void>;
/**
* Custom component event handler called when canvas size has changed (only used when canvas size is initially given as reactive value).
*/
onresize: Fn3<HTMLCanvasElement, CanvasRenderingContext2D, number[], void>;
/**
* Standard Canvas2D context options
*/
ctx: CanvasRenderingContext2DSettings;
[id: string]: any;
}

/**
* Reactive {@link @thi.ng/hiccup-canvas} component wrapper. Returns a
* canvas component wrapped in a {@link $sub} and updates/re-renders
Expand All @@ -24,7 +46,7 @@ import { sideEffect } from "@thi.ng/transducers/side-effect";
export const $canvas = (
body: ISubscription<any, any[] | IToHiccup>,
size: number[] | ISubscription<any, number[]>,
attribs?: any
attribs?: Partial<CanvasOpts>
) => $sub(body, new $Canvas(size, attribs));

export class $Canvas
Expand All @@ -39,7 +61,7 @@ export class $Canvas

constructor(
size: number[] | ISubscription<any, number[]>,
protected attribs: any = {}
protected attribs: Partial<CanvasOpts> = {}
) {
super();
this.size = isSubscribable(size)
Expand All @@ -55,16 +77,26 @@ export class $Canvas
index: NumOrElement,
shapes: any[] | IToHiccup
) {
this.inner = this.$compile(["canvas", this.attribs]);
this.inner = this.$compile([
"canvas",
withoutKeysObj(this.attribs, [
"onmount",
"onunmount",
"onresize",
"ctx",
]),
]);
this.el = <HTMLCanvasElement>await this.inner.mount(parent, index);
this.ctx = this.el.getContext("2d")!;
this.ctx = this.el.getContext("2d", this.attribs.ctx)!;
this.resize(this.size.deref()!);
this.attribs.onmount && this.attribs.onmount(this.el, this.ctx);
this.update(shapes);
return this.el;
}

async unmount() {
this.inner!.unmount();
this.el && this.attribs.onunmount && this.attribs.onunmount(this.el);
await this.inner!.unmount();
this.sizeSub.unsubscribe();
this.inner = undefined;
this.el = undefined;
Expand All @@ -74,6 +106,8 @@ export class $Canvas
resize(size: number[]) {
if (this.el) {
adaptDPI(this.el!, size[0], size[1]);
this.attribs.onresize &&
this.attribs.onresize(this.el, this.ctx!, size);
}
}

Expand All @@ -82,8 +116,12 @@ export class $Canvas
const shapes = implementsFunction(tree, "toHiccup")
? tree.toHiccup()
: tree;
shapes[1].__clear !== false &&
if (shapes[1].__bg) {
this.ctx!.fillStyle = resolveColor(shapes[1].__bg);
this.ctx!.fillRect(0, 0, this.el!.width, this.el!.height);
} else if (shapes[1].__clear !== false) {
this.ctx!.clearRect(0, 0, this.el!.width, this.el!.height);
}
const scale = window.devicePixelRatio || 1;
this.ctx!.resetTransform();
this.ctx!.scale(scale, scale);
Expand Down

0 comments on commit a579904

Please sign in to comment.