import './App.css'; import {useLayoutEffect, useState} from "react"; let mouseDownMenuBar = false let mouseDownCanvas = false let mouseMenuBarOffsetX, mouseMenuBarOffsetY = 0 let context let canvas let downLink let lastPositions = [] let strokeWidth = 5 let lastMouse = 0 let eraserColor = "rgb(255, 255, 255)" let lastStrokeWidthPencil = 5, lastStrokeWidthEraser = 5, lastStrokeWidthRect = 5 let formAnchor = null; export default function App() { useLayoutEffect(() => { canvas = document.getElementById("canvas") context = canvas.getContext("2d") clearScreen("rgb(255, 255, 255)") downLink = document.createElement("a") downLink.className = "no-display" window.scrollTo((5000 / window.innerWidth) * 500, (3000 / window.innerHeight) * 300) setInterval(() => { if(selectedTool === "pencil" || selectedTool === "eraser") { if (lastPositions.length >= 2) { let point1 = lastPositions.shift() let point2 = lastPositions[lastPositions.length - 1] let connection = new Position(point1.x - point2.x, point1.y - point2.y) for (let i = 0; i < 1; i += 0.001) { context.beginPath() context.arc(point1.x - (connection.x * i), point1.y - (connection.y * i), strokeWidth, 0, 2 * Math.PI, false) context.fill() } } else if (Date.now() - lastMouse > 100 && lastPositions.length >= 1) { let point = lastPositions.shift() context.beginPath() context.arc(point.x, point.y, strokeWidth, 0, 2 * Math.PI, false) context.fill() } } }, 1) }, []) const [menuBarLeft, setMenuBarLeft] = useState(50) const [menuBarTop, setMenuBarTop] = useState(50) const [strokeWidthSliderValue, setStrokeWidthSliderValue] = useState(strokeWidth) const [colorValue, setColorValue] = useState("#000000") const [menuBarShown, setMenuBarShown] = useState(true) const [selectedTool, setSelectedTool] = useState("pencil") const [displayRectHint, setDisplayRectHint] = useState(false) const [rectHintX, setRectHintX] = useState(0) const [rectHintY, setRectHintY] = useState(0) const [rectHintWidth, setRectHintWidth] = useState(0) const [rectHintHeight, setRectHintHeight] = useState(0) class Position { constructor(x, y) { this.x = x this.y = y } } function clearScreen(color) { context.fillStyle = color context.fillRect(0, 0, 5000, 3000) eraserColor = color } function handleMouseDownCanvas(e) { mouseDownCanvas = true context.fillStyle = selectedTool !== "eraser" ? colorValue : eraserColor if(selectedTool === "pencil" || selectedTool === "eraser") { context.beginPath() context.arc(e.pageX, e.pageY, strokeWidthSliderValue, 0, 2 * Math.PI, false) context.fill() lastMouse = Date.now() lastPositions.push(new Position(e.pageX, e.pageY)) } else if(selectedTool === "rect") { formAnchor = new Position(e.pageX, e.pageY) setRectHintX(e.pageX) setRectHintY(e.pageY) setRectHintWidth(0) setRectHintHeight(0) setDisplayRectHint(true) } } function handleMouseUpCanvas(e) { mouseDownCanvas = false if(selectedTool === "rect") { context.strokeStyle = colorValue context.beginPath() context.rect(formAnchor.x, formAnchor.y, e.pageX - formAnchor.x, e.pageY - formAnchor.y) context.lineWidth = strokeWidthSliderValue context.stroke() setDisplayRectHint(false) } } function handleMouseMove(e) { let mouseX = e.pageX let mouseY = e.pageY if (mouseDownMenuBar) { setMenuBarLeft(mouseX - mouseMenuBarOffsetX) setMenuBarTop(mouseY - mouseMenuBarOffsetY) } else if (mouseDownCanvas) { if(selectedTool === "pencil" || selectedTool === "eraser") { context.fillStyle = selectedTool !== "eraser" ? colorValue : eraserColor lastPositions.push(new Position(mouseX, mouseY)) lastMouse = Date.now() } else if(selectedTool === "rect") { if(e.pageX >= formAnchor.x) { setRectHintX(formAnchor.x) setRectHintWidth(e.pageX - formAnchor.x) } else { setRectHintX(e.pageX) setRectHintWidth(formAnchor.x - e.pageX) } if(e.pageY >= formAnchor.y) { setRectHintY(formAnchor.y) setRectHintHeight(e.pageY - rectHintY) } else { setRectHintY(e.pageY) setRectHintHeight(formAnchor.y - e.pageY) } } } } function onExportButtonClick(e) { let img = canvas.toDataURL("image/png") let image = new Image() image.src = "data:image/png;base64," + img downLink.href = img downLink.download = "export.png" downLink.click() } function handleToolChange(e) { setSelectedTool(e.target.value) if (e.target.value === "pencil") { setStrokeWidthSliderValue(lastStrokeWidthPencil) strokeWidth = lastStrokeWidthPencil } else if (e.target.value === "eraser") { setStrokeWidthSliderValue(lastStrokeWidthEraser) strokeWidth = lastStrokeWidthEraser } else if (e.target.value === "rect") { setStrokeWidthSliderValue(lastStrokeWidthRect) strokeWidth = lastStrokeWidthRect } } return (
handleMouseMove(e)} style={{overflow: "unset"}}> { handleMouseDownCanvas(e) }} onMouseUp={e => { handleMouseUpCanvas(e) }} >
); }