import { useEffect, useRef, useState } from 'preact/hooks' import { simplifyCurve } from '../../lib/math/curves.js' class KnotSimulation { constructor(knotRef) { this.knotRef = knotRef this.ghostPath = null } onMouseDrag(x, y) { if (!this.ghostPath) { this.ghostPath = [] } this.ghostPath.push([x, y]) } onMouseUp() { this.knotRef.current.points = simplifyCurve(this.ghostPath, 15) this.ghostPath = null } update() {} /** @param {CanvasRenderingContext2D} g */ render(g) { const w = g.canvas.width const h = g.canvas.height const knot = this.knotRef.current g.clearRect(0, 0, w, h) g.lineWidth = 3 g.lineCap = 'round' g.lineJoin = 'round' g.strokeStyle = '#333' if (this.ghostPath && this.ghostPath.length > 0) { g.strokeStyle = '#888' g.beginPath() { const [x0, y0] = this.ghostPath[0] g.moveTo(x0, y0) for (const [x, y] of this.ghostPath) { g.lineTo(x, y) } } g.stroke() } else if (knot.points.length > 0) { g.beginPath() const [x0, y0] = knot.points[0] g.moveTo(x0, y0) for (const [x, y] of knot.points) { g.lineTo(x, y) } g.stroke() g.fillStyle = '#080' for (const [x, y] of knot.points) { g.beginPath() g.ellipse(x, y, 3, 3, 0, 0, Math.PI * 2) g.fill() } } } } export const KnotLayer = ({ knotRef }) => { const canvasRef = useRef(null) const [knotSim] = useState(() => new KnotSimulation(knotRef)) useEffect(() => { window.addEventListener('resize', () => { // trigger repaint and get a new context }) }, []) useEffect(() => { let simTimerHandle if (canvasRef.current) { canvasRef.current.width = canvasRef.current.offsetWidth canvasRef.current.height = canvasRef.current.offsetHeight const g = canvasRef.current.getContext('2d') simTimerHandle = setInterval(() => { knotSim.update() requestAnimationFrame(() => knotSim.render(g)) console.log('Prova') }, 1000 / 30) } return () => { if (simTimerHandle) { clearInterval(simTimerHandle) } } }, [canvasRef.current]) return ( { if (e.buttons === 1) { knotSim.onMouseDrag(e.offsetX, e.offsetY) } }} onMouseMove={e => { if (e.buttons === 1) { knotSim.onMouseDrag(e.offsetX, e.offsetY) } }} onMouseUp={e => { knotSim.onMouseUp() }} /> ) }