如何解决Canvas Api无法在React中正确反映
我对Canvas API还是很陌生,并试图通过在React中编写一个绘图程序来熟悉它。
我想具有一个允许在绘制时在X轴或Y轴上进行反射的功能。我已经总结了我的绘画逻辑,可以在下面编写的钩子中与Canvas进行通信。
它正在工作,但是现在当我关闭用于打开反射的道具(reflectX或reflectY)时,我无法将其恢复为非反射图形。
我不太确定这是React问题还是Canvas问题。
任何帮助将不胜感激,谢谢!
import { useState,useEffect } from "react"
import { canvasLogic } from "../../@types/props"
import { coords,colorStop } from "../../@types/objects"
import {
brush,eraser,freehand,grad,solid,} from "../../constants/drawingOptionsTypes"
const useCanvasLogic = ({
innerWidth,innerHeight,devicePixelRatio,toolOptions,canvasRef,}: canvasLogic): void => {
const [context,setContext] = useState<CanvasRenderingContext2D | null>(null)
useEffect((): void => {
let mouseDown: boolean = false
let [canvasOffsetLeft,canvasOffsetTop]: number[] = [0,0]
let start: coords
let end: coords
const points: coords[] = []
const {
reflectX,reflectY,isClear,lineWidth,currentTool,solidOrGrad,solidColor,colorStops,} = toolOptions
const root: HTMLElement = document.getElementById("root")
let tempCanvas: HTMLCanvasElement,tempContext: CanvasRenderingContext2D
const handleMouseDown = ({ clientX,clientY }: MouseEvent): void => {
if (context) {
start = {
x: clientX - canvasOffsetLeft,y: clientY - canvasOffsetTop,}
end = start
mouseDown = true
if (root.children.length < 3) {
tempCanvas = document.createElement("canvas")
tempCanvas.id = "temp-canvas"
root.appendChild(tempCanvas)
} else tempCanvas = document.getElementById("temp-canvas")
tempContext = tempCanvas.getContext("2d")
tempCanvas.width = innerWidth
tempCanvas.height = innerHeight
if (currentTool === brush || currentTool === eraser)
tempContext.lineWidth = lineWidth
if (solidOrGrad === solid) {
if (currentTool === brush || currentTool === eraser) {
tempContext.strokeStyle = solidColor
tempContext.fillStyle = "#FFFFFF00"
} else if (currentTool === freehand) {
tempContext.strokeStyle = "#FFFFFF00"
tempContext.fillStyle = solidColor
}
}
if (solidOrGrad === grad) {
const gradient: CanvasGradient = context.createLinearGradient(
canvasOffsetTop,canvasOffsetLeft,end.x,end.y
)
colorStops.forEach((colorStop: colorStop): void => {
gradient.addColorStop(colorStop.position,colorStop.color)
})
if (currentTool === brush || currentTool === eraser) {
tempContext.strokeStyle = gradient
tempContext.fillStyle = "#FFFFFF00"
} else if (currentTool === freehand) {
tempContext.strokeStyle = "#FFFFFF00"
tempContext.fillStyle = gradient
}
}
}
}
const handleMouseMove = ({ clientX,clientY }: MouseEvent): void => {
if (mouseDown && context && tempContext) {
context.save()
start = {
x: end.x,y: end.y,}
end = {
x: clientX + canvasOffsetLeft,y: clientY + canvasOffsetTop,}
points.push(start)
const firstPoint: coords = points[0]
tempContext.beginPath()
tempContext.arc(firstPoint.x,firstPoint.y,Math.PI * 2)
tempContext.closePath()
tempContext.beginPath()
tempContext.moveTo(firstPoint.x,firstPoint.y)
const loopLength: number = points.length
if (loopLength)
for (let i = 1; i < loopLength - 2; i++) {
const bezierX: number = points[i].x
const bezierY: number = points[i].y
const endX: number = (bezierX + points[i].x) / 2
const endY: number = (bezierY + points[i].y) / 2
tempContext.quadraticCurveTo(bezierX,bezierY,endX,endY)
}
if (currentTool === brush || currentTool === eraser)
tempContext.stroke()
else if (currentTool === freehand) tempContext.fill()
tempContext.closePath()
context.drawImage(tempCanvas,0)
if (reflectX) {
tempContext.transform(-1,1,innerWidth,0)
context.drawImage(tempCanvas,0)
} else if (reflectY) {
tempContext.transform(1,-1,innerHeight)
context.drawImage(tempCanvas,0)
}
}
}
const handleMouseUp = (): void => {
if (mouseDown && context) {
mouseDown = false
points.length = 0
}
}
if (canvasRef.current) {
const renderContext = canvasRef.current.getContext("2d")
if (renderContext) {
canvasRef.current.addEventListener("mousedown",handleMouseDown)
canvasRef.current.addEventListener("mousemove",handleMouseMove)
canvasRef.current.addEventListener("mouseup",handleMouseUp)
canvasOffsetLeft = canvasRef.current.offsetLeft
canvasOffsetTop = canvasRef.current.offsetTop
setContext(renderContext)
}
if (context) {
context.scale(devicePixelRatio,devicePixelRatio)
}
}
},[context,toolOptions])
}
export default useCanvasLogic
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。