draw.jsx
1.9 kB · jsx · 48 lines
1import { useEffect, useRef } from 'react';2import { paint, blit, signs } from './mrly.js';34export function useCanvas(draw, deps, live = false, outer) {5 const inner = useRef(null);6 const ref = outer ?? inner;7 useEffect(() => {8 draw(ref.current);9 const on = () => draw(ref.current);10 addEventListener('theme', on);11 if (live) addEventListener('resize', on);12 return () => {13 removeEventListener('theme', on);14 removeEventListener('resize', on);15 };16 }, deps);17 return ref;18}1920export function Grid({ grid, on, off, canvasRef, className = 'sheet', ...rest }) {21 const ref = useCanvas((canvas) => paint(canvas, grid, on, off), [grid, on, off], false, canvasRef);22 return <canvas ref={ref} className={className} {...rest} />;23}2425export function Signs({ grid, hues, canvasRef, className = 'sheet', ...rest }) {26 const ref = useCanvas((canvas) => signs(canvas, grid, hues), [grid, hues], false, canvasRef);27 return <canvas ref={ref} className={className} {...rest} />;28}2930export function Pixels({ data, canvasRef, className = 'sheet', ...rest }) {31 const ref = useCanvas((canvas) => blit(canvas, data), [data], false, canvasRef);32 return <canvas ref={ref} className={className} {...rest} />;33}3435export function Sketch({ draw, deps = [], onSeek, pad = 14, className = 'sheet', ...rest }) {36 const ref = useCanvas(draw, deps, true);37 const at = (event) => {38 const box = ref.current.getBoundingClientRect();39 onSeek((event.clientX - box.left - pad) / (box.width - 2 * pad));40 };41 const down = onSeek ? (event) => { ref.current.setPointerCapture(event.pointerId); at(event); } : undefined;42 const move = onSeek ? (event) => { if (event.buttons) at(event); } : undefined;43 return <canvas ref={ref} className={className} onPointerDown={down} onPointerMove={move} {...rest} />;44}4546export function Markup({ svg, ...rest }) {47 return <div {...rest} dangerouslySetInnerHTML={{ __html: svg }} />;48}