以下分析均采用 Sigmajs 框架源码进行分析,有兴趣的同学可以去查看一下。 本文主要介绍下Canvas的事件机制,和一些设计思路。
图形事件,设计思路及实现介绍。
图形事件需要支持以下的内容:
- 支持各类事件类型
- 事件触发机制
- 事件冲突问题
事件类型
mouse
- mousedown
- mousemove
- mouseup
- mouseenter
- mouseleave
- dblclick
- contextmenu
- click
- wheel
- drag 基于mousedown move leave做二次开发.
- dragstart
- dragend
touch
- touchstart
- touchend
- touchcancel
- touchmove
事件触发机制
根据事件的触发源不同可以分为两种:
- 图形上触发
- Canvas上触发
所有事件均在Canvas的DOM事件触发基础上实现。
以click为例:
鼠标在画布上点击 触发Canvas DOM事件,然后与图形进行碰撞 如果有就是图形点击 没有就是画布点击。伪代码示例:
Canvas.addEventListener("click", function(){
// MouseCoords == CanvasCoords
// getShapeAtPoint(Shapes,CanvasCoords)
if(true){
// 如果碰撞到图形
this.emit("clickGraph",false);
return
}
this.emit("clickCanvas",false);
//
}, false);
事件冲突问题
drag 和 click 的冲突
由于 canvas 是一个DOM节点, 不是每个图元作为DOM 对象可以识别,所以无法通过 dragable 设置图形是否可以拖拽,这时候使用触摸板时的点击和拖拽会冲突。
在使用 mousedown,mouseup 过程中进行模拟, 对于在两者之间判定移动的距离和时间差进行一个判断。
具体是Click还是drag事件。
click 和 dbclick的冲突
其实不算是冲突问题, 是对于dbclick的实现基于click那么就需要对click事件有一个处理,方便识别。请看代码示例:
handleClick(e: MouseEvent): void {
if (!this.enabled) return;
this.clicks++;
if (this.clicks === 2) {
this.clicks = 0;
if (typeof this.doubleClickTimeout === "number") {
clearTimeout(this.doubleClickTimeout);
this.doubleClickTimeout = null;
}
return this.handleDoubleClick(e);
}
setTimeout(() => {
this.clicks = 0;
this.doubleClickTimeout = null;
}, DOUBLE_CLICK_TIMEOUT);
if (this.draggedEvents < DRAGGED_EVENTS_TOLERANCE) this.emit("click", getMouseCoords(e, this.container));
}
其他
关于事件的冒泡, 在Sigma中存在图形和画布,以及画布做了分层。彼此存在事件先后(冒泡)顺序。
最后
可视化相关的架构设计,源码学习,日常开发。我会逐步进行深入分享。如果对你有帮助请关注我后续的内容。有需要的同学可以加一下我的联系方式(在我的主页,拉你进群聊)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。