Untitled
unknown
typescript
a year ago
5.3 kB
4
Indexable
import { Stage, Sprite } from "@pixi/react"; import * as PIXI from "pixi.js"; import { useState, useEffect, useRef } from "react"; import BrushGenerator from "../../components/painters/brushGenerator.ts"; import BrushPaint from "../../components/painters/brushPaint.ts"; import { PainterConfig } from "../../components/painters/ipainter.ts"; import { PainterType } from "../../components/painters/painterType.ts"; import { Constant } from "../../constant.ts"; interface History { layerPointer: number; layers: PIXI.RenderTexture[]; currentLayer: PIXI.RenderTexture; } export default function DrawingComponent() { const spriteRef = useRef<PIXI.Sprite>(null); const [app, setApp] = useState<PIXI.Application>(null); const [isDrawing, setIsDrawing] = useState(false); const [brush, setBrush] = useState<BrushPaint>(null); const [drawingBuffer] = useState(new PIXI.Container()); const [painterConfig, setPainterConfig] = useState<PainterConfig>({ type : PainterType.Brush, size : 10, opacity : 1, smoothing : 0.5, color : "#55ec50", }); const [history, setHistory] = useState<History>({ layerPointer : 0, layers : [], currentLayer : null, }); const render = () => { if (drawingBuffer.children.length > 0 && history.currentLayer) { app.renderer.render(drawingBuffer, { renderTexture: history.currentLayer, clear: false }); } }; const init = () => { if (!app || !app.stage) { return; } app.ticker.add(render); BrushGenerator.init(app.renderer as PIXI.Renderer); setPainterConfig({ ...painterConfig }); return () => { app.ticker.remove(render); }; }; const onPainterConfigChange = () => { if (!app) { return; } setBrush(new BrushPaint(painterConfig)); }; const onHistoryChange = () => { if (!app || !spriteRef.current) { return; } console.log("history changed", history); if (history.currentLayer) { spriteRef.current.texture = history.currentLayer; } app.ticker.remove(render); app.ticker.add(render); window.addEventListener("keydown", onKeydown); return () => { app.ticker.remove(render); window.removeEventListener("keydown", onKeydown); }; }; const onDown = (e: PIXI.FederatedPointerEvent) => { if (!brush) { return; } setIsDrawing(true); createLayer(); brush.startDraw(drawingBuffer, e.global); }; const onMove = (e: PIXI.FederatedPointerEvent) => { if (!isDrawing || !brush) { return; } brush.draw(e.global); }; const onUp = () => { if (!isDrawing || !brush) { return; } setIsDrawing(false); brush.endDraw(); }; const undo = () => { if (history.layerPointer > 0) { let newHistory = { ...history }; newHistory.layerPointer--; newHistory.currentLayer = newHistory.layers[history.layerPointer]; setHistory(newHistory); } }; const redo = () => { if (history.layerPointer < history.layers.length - 1) { let newHistory = { ...history }; newHistory.layerPointer++; newHistory.currentLayer = history.layers[history.layerPointer]; setHistory(newHistory); } }; const onKeydown = (e: KeyboardEvent) => { if (e.key === "z" && e.ctrlKey) { if (e.shiftKey) { redo(); } else { undo(); } } else if (e.key === "y" && e.ctrlKey) { redo(); } }; const createLayer = (): PIXI.RenderTexture | null => { if (!app || !spriteRef.current) { return null; } let layer = PIXI.RenderTexture.create({ width : Constant.DRAW_BOARD_WIDTH, height : Constant.DRAW_BOARD_HEIGHT, }); let newHistory = { ...history }; app.renderer.render(spriteRef.current, { renderTexture: layer, clear: false }); if (history.layerPointer !== history.layers.length - 1) { let deletedLayers = history.layers.splice(history.layerPointer + 1); deletedLayers.forEach((l) => l.destroy()); } newHistory.layers = [...history.layers, layer]; newHistory.layerPointer = newHistory.layers.length - 1; newHistory.currentLayer = layer; setHistory(newHistory); return layer; }; useEffect(init, [app]); useEffect(onPainterConfigChange, [painterConfig]); useEffect(onHistoryChange, [history]); return ( <div className="w-full h-full flex justify-center items-center" > <Stage width={Constant.DRAW_BOARD_WIDTH} height={Constant.DRAW_BOARD_HEIGHT} options={{ backgroundColor : 0xffffff, backgroundAlpha : 1, antialias : true, }} onMount={setApp}> <Sprite ref={spriteRef} eventMode={"static"} width={Constant.DRAW_BOARD_WIDTH} height={Constant.DRAW_BOARD_HEIGHT} texture={PIXI.Texture.EMPTY} onmousedown={onDown} onmousemove={onMove} onmouseup={onUp} ontouchstart={onDown} ontouchmove={onMove} ontouchend={onUp} /> </Stage> </div> ); }
Editor is loading...
Leave a Comment