machineuser
Sync widgets demo
9d298eb
raw
history blame
2.08 kB
<script lang="ts">
import type { ImageSegment } from "../../shared/types.js";
import { afterUpdate } from "svelte";
export let classNames = "";
export let highlightIndex: number;
export let imgSrc = "";
export let mousemove: (e: Event, canvasW: number, canvasH: number) => void = () => {};
export let mouseout: () => void = () => {};
export let output: ImageSegment[] = [];
let containerEl: HTMLElement;
let canvas: HTMLCanvasElement;
let imgEl: HTMLImageElement;
let width = 0;
let height = 0;
let startTs: DOMHighResTimeStamp;
const animDuration = 200;
function draw() {
width = containerEl.clientWidth;
height = containerEl.clientHeight;
startTs = performance.now();
darwHelper();
}
function darwHelper() {
const maskToDraw = output.reduce((arr: any[], o, i) => {
const mask = o?.bitmap;
if (mask && (i === highlightIndex || highlightIndex === -1)) {
arr.push(mask);
}
return arr;
}, []);
const ctx = canvas?.getContext("2d");
if (ctx) {
const duration = performance.now() - startTs;
ctx.globalAlpha = Math.min(duration, animDuration) / animDuration;
ctx.drawImage(imgEl, 0, 0, width, height);
for (const mask of maskToDraw) {
ctx.drawImage(mask, 0, 0, width, height);
}
if (duration < animDuration) {
// when using canvas, prefer to use requestAnimationFrame over setTimeout & setInterval
// https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
window.requestAnimationFrame(darwHelper);
}
}
}
afterUpdate(draw);
</script>
<svelte:window on:resize={draw} />
<div class="relative top-0 left-0 inline-flex {classNames}" bind:this={containerEl}>
<div class="flex max-w-sm justify-center">
<img alt="" class="relative top-0 left-0 object-contain" src={imgSrc} bind:this={imgEl} />
</div>
{#if output.length}
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
<canvas
class="absolute top-0 left-0"
{width}
{height}
bind:this={canvas}
on:mousemove={(e) => mousemove(e, width, height)}
on:mouseout={mouseout}
/>
{/if}
</div>