mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-01-12 17:28:56 +01:00
decent drawing tools
This commit is contained in:
parent
8b48ad77e8
commit
346d1dddba
@ -2,19 +2,16 @@ import { style, globalStyle } from "@vanilla-extract/css";
|
||||
|
||||
export const DrawImageMain = style({
|
||||
position: "relative",
|
||||
width: "512px",
|
||||
height: "512px",
|
||||
});
|
||||
|
||||
globalStyle(`${DrawImageMain} > canvas`, {
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
left: "0",
|
||||
opacity: "0.5",
|
||||
opacity: ".5",
|
||||
});
|
||||
|
||||
globalStyle(`${DrawImageMain} > img`, {
|
||||
position: "absolute",
|
||||
top: "0",
|
||||
left: "0",
|
||||
});
|
||||
|
@ -1,22 +1,27 @@
|
||||
// @ts-nocheck
|
||||
import React, { useRef, useState } from "react";
|
||||
import React, { useRef, useState, useCallback, useEffect } from "react";
|
||||
|
||||
// https://github.com/embiem/react-canvas-draw
|
||||
|
||||
type DrawImageProps = {
|
||||
imageData: string;
|
||||
brushSize: string;
|
||||
|
||||
brushShape: string;
|
||||
brushColor: string;
|
||||
isErasing: boolean;
|
||||
|
||||
};
|
||||
|
||||
import {
|
||||
DrawImageMain, //@ts-ignore
|
||||
} from "./drawImage.css.ts";
|
||||
|
||||
export default function DrawImage({ imageData }: DrawImageProps) {
|
||||
export default function DrawImage({ imageData, brushSize, brushShape, brushColor, isErasing }: DrawImageProps) {
|
||||
|
||||
const drawingRef = useRef<HTMLCanvasElement>(null);
|
||||
const cursorRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
const [isDrawing, setIsDrawing] = useState(false);
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
|
||||
const _handleMouseDown = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
@ -27,95 +32,100 @@ export default function DrawImage({ imageData }: DrawImageProps) {
|
||||
nativeEvent: { offsetX, offsetY },
|
||||
} = e;
|
||||
|
||||
setIsDrawing(true);
|
||||
setIsUpdating(true);
|
||||
};
|
||||
|
||||
const _handleMouseUp = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
setIsDrawing(false);
|
||||
|
||||
setIsUpdating(false);
|
||||
const canvas = drawingRef.current;
|
||||
if (canvas) {
|
||||
const data = canvas.toDataURL();
|
||||
console.log("data", data);
|
||||
// TODO: SEND THIS TO THE STATE
|
||||
}
|
||||
};
|
||||
|
||||
const _handleMouseMove = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
if (isDrawing) {
|
||||
const canvas = drawingRef.current;
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.strokeStyle = "red";
|
||||
const {
|
||||
nativeEvent: { offsetX, offsetY },
|
||||
} = e;
|
||||
const _drawCanvas = (x, y, brushSize, brushShape, brushColor) => {
|
||||
const canvas = drawingRef.current;
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (isErasing) {
|
||||
|
||||
// stack overflow https://stackoverflow.com/questions/10396991/clearing-circular-regions-from-html5-canvas
|
||||
|
||||
const offset = brushSize / 2;
|
||||
ctx.clearRect(x - offset, y - offset, brushSize, brushSize);
|
||||
|
||||
} else {
|
||||
ctx.beginPath();
|
||||
|
||||
ctx.lineWidth = 20;
|
||||
|
||||
// Sets the end of the lines drawn
|
||||
// to a round shape.
|
||||
ctx.lineCap = "round";
|
||||
|
||||
ctx.strokeStyle = "white";
|
||||
// The cursor to start drawing
|
||||
// moves to this coordinate
|
||||
ctx.moveTo(offsetX, offsetY);
|
||||
|
||||
// A line is traced from start
|
||||
// coordinate to this coordinate
|
||||
ctx.lineTo(offsetX, offsetY);
|
||||
|
||||
// Draws the line.
|
||||
ctx.lineWidth = brushSize;
|
||||
ctx.lineCap = brushShape;
|
||||
ctx.strokeStyle = brushColor;
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x, y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _handleCursorMove = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
console.log("cursor move");
|
||||
|
||||
|
||||
const _drawCursor = (x, y, brushSize, brushShape, brushColor) => {
|
||||
const canvas = cursorRef.current;
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.strokeStyle = "red";
|
||||
const {
|
||||
nativeEvent: { offsetX, offsetY },
|
||||
} = e;
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.lineWidth = 20;
|
||||
if (isErasing) {
|
||||
const offset = brushSize / 2;
|
||||
// draw a quare outline
|
||||
ctx.lineWidth = 2;
|
||||
ctx.lineCap = 'butt';
|
||||
ctx.strokeStyle = brushColor;
|
||||
ctx.moveTo(x - offset, y - offset);
|
||||
ctx.lineTo(x + offset, y - offset);
|
||||
ctx.lineTo(x + offset, y + offset);
|
||||
ctx.lineTo(x - offset, y + offset);
|
||||
ctx.lineTo(x - offset, y - offset);
|
||||
ctx.stroke();
|
||||
|
||||
// Sets the end of the lines drawn
|
||||
// to a round shape.
|
||||
ctx.lineCap = "round";
|
||||
} else {
|
||||
|
||||
ctx.strokeStyle = "white";
|
||||
// The cursor to start drawing
|
||||
// moves to this coordinate
|
||||
ctx.moveTo(offsetX, offsetY);
|
||||
ctx.lineWidth = brushSize;
|
||||
ctx.lineCap = brushShape;
|
||||
ctx.strokeStyle = brushColor;
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x, y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
// A line is traced from start
|
||||
// coordinate to this coordinate
|
||||
ctx.lineTo(offsetX, offsetY);
|
||||
};
|
||||
|
||||
// Draws the line.
|
||||
ctx.stroke();
|
||||
const _handleMouseMove = (
|
||||
e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
|
||||
) => {
|
||||
|
||||
const {
|
||||
nativeEvent: { offsetX: x, offsetY: y },
|
||||
} = e;
|
||||
|
||||
_drawCursor(x, y, brushSize, brushShape, brushColor);
|
||||
|
||||
if (isUpdating) {
|
||||
_drawCanvas(x, y, brushSize, brushShape, brushColor);
|
||||
}
|
||||
};
|
||||
|
||||
// function for external use
|
||||
const fillCanvas = () => {
|
||||
const canvas = drawingRef.current;
|
||||
if (canvas) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = brushColor;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={DrawImageMain}>
|
||||
@ -124,17 +134,15 @@ export default function DrawImage({ imageData }: DrawImageProps) {
|
||||
ref={drawingRef}
|
||||
width={512}
|
||||
height={512}
|
||||
onMouseDown={_handleMouseDown}
|
||||
onMouseMove={_handleMouseMove}
|
||||
onMouseUp={_handleMouseUp}
|
||||
></canvas>
|
||||
<canvas
|
||||
ref={cursorRef}
|
||||
width={512}
|
||||
height={512}
|
||||
onMouseMove={_handleCursorMove}
|
||||
onMouseDown={_handleMouseDown}
|
||||
onMouseUp={_handleMouseUp}
|
||||
onMouseMove={_handleMouseMove}
|
||||
></canvas>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -12,8 +12,6 @@ export const InpaintingSlider = style({
|
||||
position: "absolute",
|
||||
top: "10px",
|
||||
left: "400px",
|
||||
width: "200px",
|
||||
height: "20px",
|
||||
zIndex: 1,
|
||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||
});
|
||||
|
@ -1,19 +1,148 @@
|
||||
import React from "react";
|
||||
import React, { useRef, useState, ChangeEvent } from "react";
|
||||
import DrawImage from "../../../molecules/drawImage";
|
||||
|
||||
import { useImageCreate } from "../../../../stores/imageCreateStore";
|
||||
|
||||
|
||||
import {
|
||||
InpaintingPanelMain,
|
||||
InpaintingControls,
|
||||
InpaintingControlRow,
|
||||
} from // @ts-ignore
|
||||
"./inpaintingPanel.css.ts";
|
||||
|
||||
export default function InpaintingPanel() {
|
||||
|
||||
// no idea if this is the right typing
|
||||
const drawingRef = useRef(null);
|
||||
|
||||
const [brushSize, setBrushSize] = useState('20');
|
||||
const [brushShape, setBrushShape] = useState("round");
|
||||
const [brushColor, setBrushColor] = useState("#fff");
|
||||
const [isErasing, setIsErasing] = useState(false);
|
||||
|
||||
const init_image = useImageCreate((state) =>
|
||||
state.getValueForRequestKey("init_image")
|
||||
);
|
||||
|
||||
const _handleBrushMask = () => {
|
||||
setIsErasing(false);
|
||||
};
|
||||
|
||||
const _handleBrushErase = () => {
|
||||
setIsErasing(true);
|
||||
};
|
||||
|
||||
const _handleFillMask = () => {
|
||||
console.log("fill mask!!", drawingRef);
|
||||
|
||||
// drawingRef.current?.fillCanvas();
|
||||
};
|
||||
|
||||
const _handleClearAll = () => {
|
||||
console.log("clear all");
|
||||
};
|
||||
|
||||
const _handleBrushSize = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setBrushSize(e.target.value);
|
||||
};
|
||||
|
||||
// const _handleBrushShape = (e: ) => {
|
||||
// console.log("brush shape", e.target.value);
|
||||
// setBrushShape(e.target.value);
|
||||
// };
|
||||
|
||||
const _handleBrushShape = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
console.log("brush shape", e.target.value);
|
||||
setBrushShape(e.target.value);
|
||||
};
|
||||
|
||||
const _handleBrushColor = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
console.log("brush color", e.target.value);
|
||||
setBrushColor(e.target.value);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DrawImage imageData={init_image} />
|
||||
<div className={InpaintingPanelMain}>
|
||||
<DrawImage
|
||||
// ref={drawingRef}
|
||||
imageData={init_image}
|
||||
brushSize={brushSize}
|
||||
brushShape={brushShape}
|
||||
brushColor={brushColor}
|
||||
isErasing={isErasing}
|
||||
/>
|
||||
<div className={InpaintingControls}>
|
||||
<div className={InpaintingControlRow}>
|
||||
<button
|
||||
onClick={_handleBrushMask}
|
||||
>
|
||||
Mask
|
||||
</button>
|
||||
<button
|
||||
onClick={_handleBrushErase}
|
||||
>
|
||||
Erase
|
||||
</button>
|
||||
<button
|
||||
disabled
|
||||
onClick={_handleFillMask}
|
||||
>
|
||||
Fill
|
||||
</button>
|
||||
<button
|
||||
disabled
|
||||
onClick={_handleClearAll}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
|
||||
<label
|
||||
>
|
||||
Brush Size
|
||||
<input
|
||||
type="range"
|
||||
min="1"
|
||||
max="100"
|
||||
value={brushSize}
|
||||
onChange={_handleBrushSize}
|
||||
>
|
||||
</input>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className={InpaintingControlRow}>
|
||||
<button
|
||||
value={"round"}
|
||||
onClick={_handleBrushShape}
|
||||
>
|
||||
Cirle Brush
|
||||
</button>
|
||||
<button
|
||||
value={"square"}
|
||||
onClick={_handleBrushShape}
|
||||
>
|
||||
Square Brush
|
||||
</button>
|
||||
|
||||
<button
|
||||
value={"#000"}
|
||||
onClick={_handleBrushColor}
|
||||
>
|
||||
Dark Brush
|
||||
</button>
|
||||
<button
|
||||
value={"#fff"}
|
||||
onClick={_handleBrushColor}
|
||||
>
|
||||
Light Brush
|
||||
</button>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,29 @@
|
||||
import { style } from '@vanilla-extract/css'
|
||||
|
||||
export const InpaintingPanelMain = style({
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
padding: '10px 10px',
|
||||
});
|
||||
|
||||
export const InpaintingControls = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
width: '100%',
|
||||
flexWrap: 'wrap',
|
||||
});
|
||||
|
||||
export const InpaintingControlRow = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-evenly',
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
|
||||
':first-of-type': {
|
||||
margin: '10px 0',
|
||||
|
||||
},
|
||||
|
||||
});
|
Loading…
Reference in New Issue
Block a user