feat: add python and web implementation
This commit is contained in:
1 parent
fabbc6d147
commit
df0950ef11
30 files changed
+5458
-8
No files matched your search
@@ -0,0 +1,66 @@
|
||||
import { useEffect, useRef, type PointerEvent } from "react";
|
||||
import { ZUSTAENDE, type Zelle } from "../modell";
|
||||
|
||||
// Zustandsfarben als RGB, einmal vorberechnet
|
||||
const FARBEN_RGB = ZUSTAENDE.map(({ farbe }) => [1, 3, 5].map((i) => parseInt(farbe.slice(i, i + 2), 16)));
|
||||
|
||||
interface Props {
|
||||
breite: number;
|
||||
hoehe: number;
|
||||
zustand: Uint8Array;
|
||||
/** Erhöhen, um neu zu zeichnen, wenn das Gitter direkt verändert wurde */
|
||||
version?: number;
|
||||
/** Wird beim Klicken und Ziehen mit der Zelle unter dem Zeiger aufgerufen */
|
||||
onZelle?: (zelle: Zelle) => void;
|
||||
beschriftung: string;
|
||||
}
|
||||
|
||||
export default function Gitter({ breite, hoehe, zustand, version, onZelle, beschriftung }: Props) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const maltRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const ctx = canvasRef.current?.getContext("2d");
|
||||
if (!ctx) return;
|
||||
const bild = ctx.createImageData(breite, hoehe);
|
||||
for (let i = 0; i < zustand.length; i++) {
|
||||
const [r, g, b] = FARBEN_RGB[zustand[i]];
|
||||
bild.data[4 * i] = r;
|
||||
bild.data[4 * i + 1] = g;
|
||||
bild.data[4 * i + 2] = b;
|
||||
bild.data[4 * i + 3] = 255;
|
||||
}
|
||||
ctx.putImageData(bild, 0, 0);
|
||||
}, [breite, hoehe, zustand, version]);
|
||||
|
||||
function zelleUnterZeiger(e: PointerEvent<HTMLCanvasElement>): Zelle {
|
||||
const rechteck = e.currentTarget.getBoundingClientRect();
|
||||
return [
|
||||
Math.floor(((e.clientY - rechteck.top) / rechteck.height) * hoehe),
|
||||
Math.floor(((e.clientX - rechteck.left) / rechteck.width) * breite),
|
||||
];
|
||||
}
|
||||
|
||||
return (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className={onZelle ? "gitter gitter--interaktiv" : "gitter"}
|
||||
width={breite}
|
||||
height={hoehe}
|
||||
style={{ aspectRatio: `${breite} / ${hoehe}` }}
|
||||
role="img"
|
||||
aria-label={beschriftung}
|
||||
onPointerDown={(e) => {
|
||||
if (!onZelle) return;
|
||||
maltRef.current = true;
|
||||
e.currentTarget.setPointerCapture(e.pointerId);
|
||||
onZelle(zelleUnterZeiger(e));
|
||||
}}
|
||||
onPointerMove={(e) => {
|
||||
if (onZelle && maltRef.current) onZelle(zelleUnterZeiger(e));
|
||||
}}
|
||||
onPointerUp={() => (maltRef.current = false)}
|
||||
onPointerCancel={() => (maltRef.current = false)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user