这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
相关阅读
- 使用konva制作在线photoshop(1)——元素拖拽、变形与导出
- 使用react-konva制作在线photoshop(2)——字体的文本与样式的修改
- 使用react-konva制作在线制图应用(3)——在线字体文件的动态渲染
- 使用react-konva制作在线制图应用(4)——撤销/重做(踩坑篇)
撤销/重做
上一篇文章中我们使用循环队列来保存每一步操作的数据。原理上是可行的,但在应用起来与react结合踩了不少的坑。接下来我们来填坑。
数据绑定
使用上一篇结尾的代码绑定到视图层后,发现当操作一步之后,再点击“撤回”无法撤回
最终效果如下
这是因为视图层的 state 为 circularQueue 的一个实例,每次改变时,react 不能捕获到他的数据变更,因此我们必须把 current 绑定到 state 上,这里不详述了,这个系列结束后会给出源代码。
元素缩放时撤回/重做失效
正当我因为把撤回重做功能测试通过而暗自窃喜时,在拖动选择框大小时却发现,每次撤回时是按帧撤回的,而不是把最后一次缩放的操作放入循环列表中。进入
Transformer
中瞧瞧:
<Transformer
ref={trRef}
boundBoxFunc={(oldBox, newBox) => {
// limit resize
if (newBox.width < 5 || newBox.height < 5) {
return oldBox
}
console.log('changedbox') // 打印一下
handleInfo(newBox)
return newBox
}}
/>
发现控制台竟然打印了 100 多次“changedbox” Σ(っ °Д °;)っ
一想就知道boundBoxFunc
是连续触发的,所以这里把每一帧的变化都传给了循环队列。本人那么多年经验的码农可不是吃 hello world 长大的!!(●'◡'●) 这里用防抖函数debounce
包裹一下,
const debounceHandleInfo = debounce((newBox) => {
trRef.current.forceUpdate()
handleInfo(newBox)
}, 100)
const boundBoxFunc = (oldBox: any, newBox: any) => {
if (newBox.width < 5 || newBox.height < 5) {
return oldBox
}
debounceHandleInfo(newBox)
return newBox
}
// ...
return <Transformer ref={trRef} boundBoxFunc={boundBoxFunc} />
运行:
woc!!(╯▔ 皿 ▔)╯ 为什么事情的发展和我想象中的不一样!Transformer 包裹的元素怎么会发生畸(ji)变?konva 内部一定是自己做了什么"见不得光"的事情,摔,去翻 api 文档...、
试了onDragEnd
、isTransforming
都差强人意,翻遍 github issue 和 stackoverflow 都没有,正当我绝望时,把鼠标挪到Transformer
那行代码上,输了一个on
,发现了神迹:onTransformEnd
。
<Transformer
ref={trRef}
boundBoxFunc={boundBoxFunc}
onTransformEnd={(a) => {
console.log('end', a)
}}
/>
打印一下康康:
发现内部
target.attrs
正是我们需要的包裹元素的属性!
赶紧给他传入循环队列中!
<Transformer
// ...
onTransformEnd={(a) => {
handleInfo(a.target.attrs)
}}
/>
wor! ε=( o ` ω′)ノ 图片倒是对了,怎么文本元素撤回时文本没了啊?
在逐层去看a.target.attrs
中并没有什么奇奇怪怪的属性,但不清楚内部是不是会触发些什么 bug,我们只能把需要的属性择出来:
<Transformer
// ...
onTransformEnd={(a) => {
const { scaleX, scaleY, rotation, skewX, skewY, x, y } = a.target.attrs
handleInfo({ scaleX, scaleY, rotation, skewX, skewY, x, y })
}}
/>
大功告成!猜想估计是绑定了什么奇奇怪怪的属性,触发了内部隐藏的功能。
这部分终于结束了,明天更新处理图层相关的操作,敬请期待!