Untitled
unknown
typescript
2 years ago
5.3 kB
6
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