我们还需要在初始化canvas的时候,我们就添加入当前的状态存入列表中,作为最先开始的空画布状态
const fillImage = async () => {
// 省略一万字... img.src = await getURLBase64(fillImageSrc)
img.onload = () => {
const imageData: ImageData = context.getImageData(0, 0, canvas.width, canvas.height)
canvasHistroyListRef.current = []canvasHistroyListRef.current.push(imageData)
setCanvasCurrentHistory(1)
}
}
然后我们就实现一下,画笔更新时候,我们也需要将当前的状态添加入 画笔状态列表 ,并且更新当前状态对应的下标,还需要处理一下一些细节
总结一下:
鼠标抬起时,获取当前canvas画布状态
添加进状态列表中,并且更新状态下标
如果当前处于撤销状态,若使用画笔更新状态,则将当前的最为最新的状态,原先位置之后的状态全部清空
const handleLineMode = (downX: number, downY: number) => {
// 省略一万字...
canvas.onmouseup = () => {
const imageData: ImageData = context.getImageData(0, 0, canvas.width, canvas.height) // 如果此时处于撤销状态,此时再使用画笔,则将之后的状态清空,以刚画的作为最新的画布状态
if (canvasCurrentHistory < canvasHistroyListRef.current.length) {
canvasHistroyListRef.current = canvasHistroyListRef.current.slice(0, canvasCurrentHistory)
}
canvasHistroyListRef.current.push(imageData)
setCanvasCurrentHistory(canvasCurrentHistory + 1)
context.closePath()
canvas.onmousemove = null
canvas.onmouseup = null
}
}
画布状态的撤销与恢复
ok,其实现在关于画布状态的更新,我们已经完成了。接下来我们需要处理一下状态的撤销与恢复的功能啦
我们先定义一下这个工具栏吧

然后我们设置对应的事件,分别是撤销,恢复,与清空,其实都很容易看懂,最多就是处理一下边界情况。
const handleRollBack = () => {
const isFirstHistory: boolean = canvasCurrentHistory === 1
if (isFirstHistory) return
setCanvasCurrentHistory(canvasCurrentHistory - 1)
}const handleRollForward = () => {
const { current: canvasHistroyList } = canvasHistroyListRef
const isLastHistory: boolean = canvasCurrentHistory === canvasHistroyList.length
if (isLastHistory) return
setCanvasCurrentHistory(canvasCurrentHistory + 1)
}
const handleClearCanvasClick = () => {
const { current: canvas } = canvasRef
const context: CanvasRenderingContext2D | undefined | null = canvas?.getContext('2d')
if (!canvas || !context || canvasCurrentHistory === 0) return









