UNPKG

@tldraw/editor

Version:

tldraw infinite canvas SDK (editor).

151 lines (150 loc) 4.29 kB
import { uniqueId } from "@tldraw/utils"; import { Vec } from "../../../primitives/Vec.mjs"; class ScribbleManager { constructor(editor) { this.editor = editor; } scribbleItems = /* @__PURE__ */ new Map(); state = "paused"; addScribble(scribble, id = uniqueId()) { const item = { id, scribble: { id, size: 20, color: "accent", opacity: 0.8, delay: 0, points: [], shrink: 0.1, taper: true, ...scribble, state: "starting" }, timeoutMs: 0, delayRemaining: scribble.delay ?? 0, prev: null, next: null }; this.scribbleItems.set(id, item); return item; } reset() { this.editor.updateInstanceState({ scribbles: [] }); this.scribbleItems.clear(); } /** * Start stopping the scribble. The scribble won't be removed until its last point is cleared. * * @public */ stop(id) { const item = this.scribbleItems.get(id); if (!item) throw Error(`Scribble with id ${id} not found`); item.delayRemaining = Math.min(item.delayRemaining, 200); item.scribble.state = "stopping"; return item; } /** * Set the scribble's next point. * * @param id - The id of the scribble to add a point to. * @param x - The x coordinate of the point. * @param y - The y coordinate of the point. * @param z - The z coordinate of the point. * @public */ addPoint(id, x, y, z = 0.5) { const item = this.scribbleItems.get(id); if (!item) throw Error(`Scribble with id ${id} not found`); const { prev } = item; const point = { x, y, z }; if (!prev || Vec.Dist(prev, point) >= 1) { item.next = point; } return item; } /** * Update on each animation frame. * * @param elapsed - The number of milliseconds since the last tick. * @public */ tick(elapsed) { if (this.scribbleItems.size === 0) return; this.editor.run(() => { this.scribbleItems.forEach((item) => { if (item.scribble.state === "starting") { const { next: next2, prev: prev2 } = item; if (next2 && next2 !== prev2) { item.prev = next2; item.scribble.points.push(next2); } if (item.scribble.points.length > 8) { item.scribble.state = "active"; } return; } if (item.delayRemaining > 0) { item.delayRemaining = Math.max(0, item.delayRemaining - elapsed); } item.timeoutMs += elapsed; if (item.timeoutMs >= 16) { item.timeoutMs = 0; } const { delayRemaining, timeoutMs, prev, next, scribble } = item; switch (scribble.state) { case "active": { if (next && next !== prev) { item.prev = next; scribble.points.push(next); if (delayRemaining === 0) { if (scribble.points.length > 8) { scribble.points.shift(); } } } else { if (timeoutMs === 0) { if (scribble.points.length > 1) { scribble.points.shift(); } else { item.delayRemaining = scribble.delay; } } } break; } case "stopping": { if (item.delayRemaining === 0) { if (timeoutMs === 0) { if (scribble.points.length === 1) { this.scribbleItems.delete(item.id); return; } if (scribble.shrink) { scribble.size = Math.max(1, scribble.size * (1 - scribble.shrink)); } scribble.points.shift(); } } break; } case "paused": { break; } } }); this.editor.updateInstanceState({ scribbles: Array.from(this.scribbleItems.values()).map(({ scribble }) => ({ ...scribble, points: [...scribble.points] })).slice(-5) // limit to three as a minor sanity check }); }); } } export { ScribbleManager }; //# sourceMappingURL=ScribbleManager.mjs.map