大家好,我是前端西瓜哥。
最近做了编组功能,整个图形编辑器的基本功能都需要重写,比如选中逻辑。
其中需要实现这么一个功能。
在某个图形上双击。
如果当前处于没有选中图形的状态,对于最顶层的组,对它们的直接子图形数组从上往下遍历,找出命中 hitTest 的图形,将其设置为选中状态。
这时子图形处于选中状态,如果这个子图形也依旧还是组对象,我们 再双击,再选中其下命中 hitTest 的子图形。依此递归。
然后我发现了一个问题。
我用的是浏览器原生的双击事件(dblclick),如果连续点击超过了两次,是无法触发多次双击事件,实现丝滑快速地自顶向下不断选中子元素的效果。
双击事件是有冷却时间的,需要停顿一段时间才能进入下一次双击事件。
如果你在极短的时间内点击了很多次,不好意思,只能触发了一次双击事件。
于是,我们需要一个连击事件。
浏览器不提供,我们就自己实现。
调试观测了一段事件,实现这么一个连击事件需要注意一下几点:
记录每次 mousedown 事件的时间戳,以及光标位置,这里记录了 pageX 和 pageY 位置。
计算两次事件的时间差和位置差,看看是否在允许的范围内。
如果在,触发 “连击事件”,否则不触发。
let pointerDownTimeStamp = -Infinity;
let lastPointerDownPos: IPoint = { x: -99, y: -99 };
// 可做成配置
const continueClickMaxGap = 350;
const continueClickDistanceTol = 5;
const onMousedown = (event: PointerEvent) => {
// 鼠标左键
if (event.button === 0) {
const now = new Date().getTime();
const newPos = {
x: event.pageX,
y: event.pageY,
};
const interval = now - pointerDownTimeStamp;
const clickDistanceDiff = distance(newPos, lastPointerDownPos);
// 如果都在范围内,触发 “连击事件
if (
interval < continueClickMaxGap &&
clickDistanceDiff < continueClickDistanceTol
) {
eventEmitter.emit('continueClick', event);
}
pointerDownTimeStamp = now;
lastPointerDownPos = newPos;
}
};
canvas.addEventListener('mousedown', onMousedown)
换成连选后,效果就变得非常丝滑了。见下图。
实现基于 Web 端的图形编辑器,其中对各种原生事件的支持和兼容也是很重要的。
我是前端西瓜哥,欢迎关注我,学习更多图形编辑器知识。