rkgk/static/brush-preview.js
リキ萌 0ddc42c00f sidebar layout
switch the app from floating panels to a static sidebar on the right with resizable tools
expect more layout bugs from now on
2025-06-27 23:24:09 +02:00

81 lines
2.2 KiB
JavaScript

import { Pixmap } from "rkgk/haku.js";
export class BrushPreview extends HTMLElement {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
connectedCallback() {
this.canvas = this.appendChild(document.createElement("canvas"));
this.ctx = this.canvas.getContext("2d");
this.#resizeCanvas();
if (this.width == null || this.height == null) {
new ResizeObserver(() => this.#resizeCanvas()).observe(this);
}
}
#resizeCanvas() {
this.canvas.width = this.width ?? this.clientWidth;
this.canvas.height = this.height ?? this.clientHeight;
// This can happen if the element's `display: none`.
if (this.canvas.width == 0 || this.canvas.height == 0) return;
if (this.pixmap != null) {
this.pixmap.destroy();
}
this.pixmap = new Pixmap(this.canvas.width, this.canvas.height);
this.dispatchEvent(new Event(".pixmapLost"));
}
async #renderBrushInner(haku) {
this.pixmap.clear();
let evalResult = await haku.evalBrush({
runDotter: async () => {
return {
fromX: this.canvas.width / 2,
fromY: this.canvas.height / 2,
toX: this.canvas.width / 2,
toY: this.canvas.height / 2,
num: 0,
};
},
runScribble: async (renderToPixmap) => {
return renderToPixmap(this.pixmap, 0, 0);
},
});
if (evalResult.status != "ok") {
return { status: "error", phase: "eval", result: evalResult };
}
this.ctx.putImageData(this.pixmap.getImageData(), 0, 0);
return { status: "ok" };
}
async renderBrush(haku) {
this.unsetErrorFlag();
let result = await this.#renderBrushInner(haku);
if (result.status == "error") {
console.error(result);
this.setErrorFlag();
}
return result;
}
unsetErrorFlag() {
this.classList.remove("error");
}
setErrorFlag() {
this.classList.add("error");
}
}
customElements.define("rkgk-brush-preview", BrushPreview);