Added Eraser

This commit is contained in:
brausjonas
2023-07-06 21:13:23 +02:00
parent bf653da744
commit d55a5f2c54
+66 -18
View File
@@ -10,14 +10,15 @@ let downLink
let lastPositions = [] let lastPositions = []
let strokeWidth = 5 let strokeWidth = 5
let lastMouse = 0 let lastMouse = 0
let eraserColor = "rgb(255, 255, 255)"
let lastStrokeWidthPencil = 5, lastStrokeWidthEraser = 5
export default function App() { export default function App() {
useLayoutEffect(() => { useLayoutEffect(() => {
canvas = document.getElementById("canvas") canvas = document.getElementById("canvas")
context = canvas.getContext("2d") context = canvas.getContext("2d")
context.fillStyle = "rgb(255, 255, 255)" clearScreen("rgb(255, 255, 255)")
context.fillRect(0, 0, window.innerWidth, window.innerHeight)
downLink = document.createElement("a") downLink = document.createElement("a")
downLink.className = "no-display" downLink.className = "no-display"
@@ -49,6 +50,7 @@ export default function App() {
const [strokeWidthSliderValue, setStrokeWidthSliderValue] = useState(strokeWidth) const [strokeWidthSliderValue, setStrokeWidthSliderValue] = useState(strokeWidth)
const [colorValue, setColorValue] = useState("#000000") const [colorValue, setColorValue] = useState("#000000")
const [menuBarShown, setMenuBarShown] = useState(true) const [menuBarShown, setMenuBarShown] = useState(true)
const [selectedTool, setSelectedTool] = useState("pencil")
class Position { class Position {
constructor(x, y) { constructor(x, y) {
@@ -57,6 +59,24 @@ export default function App() {
} }
} }
function clearScreen(color) {
context.fillStyle = color
context.fillRect(0, 0, window.innerWidth, window.innerHeight)
eraserColor = color
}
function handleMouseDownCanvas(e)
{
mouseDownCanvas = true
context.fillStyle = selectedTool === "pencil" ? colorValue : eraserColor
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))
}
function handleMouseMove(event) { function handleMouseMove(event) {
let mouseX = event.pageX let mouseX = event.pageX
let mouseY = event.pageY let mouseY = event.pageY
@@ -66,7 +86,7 @@ export default function App() {
setMenuBarLeft(mouseX - mouseMenuBarOffsetX) setMenuBarLeft(mouseX - mouseMenuBarOffsetX)
setMenuBarTop(mouseY - mouseMenuBarOffsetY) setMenuBarTop(mouseY - mouseMenuBarOffsetY)
} else if (mouseDownCanvas) { } else if (mouseDownCanvas) {
context.fillStyle = colorValue context.fillStyle = selectedTool === "pencil" ? colorValue : eraserColor
lastPositions.push(new Position(mouseX, mouseY)) lastPositions.push(new Position(mouseX, mouseY))
@@ -83,6 +103,19 @@ export default function App() {
downLink.click() 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
}
}
return ( return (
<div onMouseMove={e => handleMouseMove(e)} style={{overflow: "unset"}}> <div onMouseMove={e => handleMouseMove(e)} style={{overflow: "unset"}}>
@@ -90,14 +123,7 @@ export default function App() {
width={window.innerWidth} width={window.innerWidth}
height={window.innerHeight} height={window.innerHeight}
onMouseDown={e => { onMouseDown={e => {
mouseDownCanvas = true handleMouseDownCanvas(e)
context.fillStyle = colorValue
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))
}} }}
onMouseUp={e => { onMouseUp={e => {
mouseDownCanvas = false mouseDownCanvas = false
@@ -157,30 +183,53 @@ export default function App() {
<div style={{ <div style={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
justifyContent: "flex-start", justifyContent: "center",
gap: 5, gap: 5,
alignItems: "center", alignItems: "center",
pointerEvents: "none" pointerEvents: "none"
}}> }}>
<div style={{ <div style={{
display: "flex", display: "flex",
flexDirection: "row", flexDirection: "row",
justifyContent: "center",
alignItems: "center",
gap: 10
}}> }}>
<div style={{display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-end", gap: 10}}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
className="bi bi-pencil-fill" viewBox="0 0 16 16"> className="bi bi-pencil-fill" viewBox="0 0 16 16">
<path <path
d="M12.854.146a.5.5 0 0 0-.707 0L10.5 1.793 14.207 5.5l1.647-1.646a.5.5 0 0 0 0-.708l-3-3zm.646 6.061L9.793 2.5 3.293 9H3.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.207l6.5-6.5zm-7.468 7.468A.5.5 0 0 1 6 13.5V13h-.5a.5.5 0 0 1-.5-.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.5-.5V10h-.5a.499.499 0 0 1-.175-.032l-.179.178a.5.5 0 0 0-.11.168l-2 5a.5.5 0 0 0 .65.65l5-2a.5.5 0 0 0 .168-.11l.178-.178z"/> d="M12.854.146a.5.5 0 0 0-.707 0L10.5 1.793 14.207 5.5l1.647-1.646a.5.5 0 0 0 0-.708l-3-3zm.646 6.061L9.793 2.5 3.293 9H3.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.207l6.5-6.5zm-7.468 7.468A.5.5 0 0 1 6 13.5V13h-.5a.5.5 0 0 1-.5-.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.5-.5V10h-.5a.499.499 0 0 1-.175-.032l-.179.178a.5.5 0 0 0-.11.168l-2 5a.5.5 0 0 0 .65.65l5-2a.5.5 0 0 0 .168-.11l.178-.178z"/>
</svg> </svg>
<p style={{userSelect: "none"}}>{strokeWidthSliderValue}</p> <input type={"radio"} name={"tool"} value={"pencil"} style={{width: 20, height: 20, pointerEvents: "auto"}}
checked={selectedTool === "pencil"} onChange={e => {
handleToolChange(e)
}}/>
</div> </div>
<div style={{display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-end", gap: 10}}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
className="bi bi-eraser-fill" viewBox="0 0 16 16">
<path
d="M8.086 2.207a2 2 0 0 1 2.828 0l3.879 3.879a2 2 0 0 1 0 2.828l-5.5 5.5A2 2 0 0 1 7.879 15H5.12a2 2 0 0 1-1.414-.586l-2.5-2.5a2 2 0 0 1 0-2.828l6.879-6.879zm.66 11.34L3.453 8.254 1.914 9.793a1 1 0 0 0 0 1.414l2.5 2.5a1 1 0 0 0 .707.293H7.88a1 1 0 0 0 .707-.293l.16-.16z"/>
</svg>
<input type={"radio"} value={"eraser"} name={"tool"} style={{width: 20, height: 20, pointerEvents: "auto"}}
checked={selectedTool === "eraser"} onChange={e => {
handleToolChange(e)
}}/>
</div>
</div>
<input type={"range"} min={1} max={20} value={strokeWidthSliderValue} onChange={e => { <input type={"range"} min={1} max={20} value={strokeWidthSliderValue} onChange={e => {
setStrokeWidthSliderValue(e.currentTarget.value) setStrokeWidthSliderValue(e.currentTarget.value)
strokeWidth = e.currentTarget.value strokeWidth = e.currentTarget.value
if(selectedTool === "pencil") {
lastStrokeWidthPencil = strokeWidth
}
else if(selectedTool === "eraser") {
lastStrokeWidthEraser = strokeWidth;
}
}} style={{pointerEvents: "auto"}}/> }} style={{pointerEvents: "auto"}}/>
<p style={{userSelect: "none"}}>{strokeWidthSliderValue}</p>
</div> </div>
{/*Color Selector*/} {/*Color Selector*/}
@@ -206,8 +255,7 @@ export default function App() {
borderRadius: 15, borderRadius: 15,
pointerEvents: "auto" pointerEvents: "auto"
}} onClick={() => { }} onClick={() => {
context.fillStyle = colorValue clearScreen(colorValue)
context.fillRect(0, 0, window.innerWidth, window.innerHeight)
}}> }}>
Clear Clear
</button> </button>