UNPKG

@antv/g6

Version:

graph visualization frame work

180 lines (173 loc) 5.17 kB
const Util = require('../../util'); const EVENTS = [ 'click', 'mousedown', 'mouseup', 'dblclick', 'contextmenu', 'mouseenter', 'mouseout', 'mouseover', 'mousemove', 'mouseleave', 'dragstart', 'dragend', 'drag', 'dragenter', 'dragleave', 'drop' ]; function getItemRoot(shape) { while (shape && !shape.get('item')) { shape = shape.get('parent'); } return shape; } const ORIGIN_MATRIX = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; const MATRIX_LEN = 9; function isViewportChanged(matrix) { for (let i = 0; i < MATRIX_LEN; i++) { if (matrix[i] !== ORIGIN_MATRIX[i]) { return true; } } return false; } class Event { constructor(graph) { this.graph = graph; this.extendEvents = []; this._initEvents(); } _initEvents() { const self = this; const graph = self.graph; const canvas = graph.get('canvas'); const el = canvas.get('el'); const extendEvents = self.extendEvents; const canvasHandler = Util.wrapBehavior(self, '_onCanvasEvents'); const originHandler = Util.wrapBehavior(self, '_onExtendEvents'); const wheelHandler = Util.wrapBehavior(self, '_onWheelEvent'); Util.each(EVENTS, event => { canvas.on(event, canvasHandler); }); this.canvasHandler = canvasHandler; extendEvents.push(Util.addEventListener(el, 'DOMMouseScroll', wheelHandler)); extendEvents.push(Util.addEventListener(el, 'mousewheel', wheelHandler)); if (typeof window !== 'undefined') { extendEvents.push(Util.addEventListener(window, 'keydown', originHandler)); extendEvents.push(Util.addEventListener(window, 'keyup', originHandler)); } } _onCanvasEvents(e) { const self = this; const graph = self.graph; const canvas = graph.get('canvas'); const pixelRatio = canvas.get('pixelRatio'); const target = e.target; const eventType = e.type; /** * (clientX, clientY): 相对于页面的坐标; * (canvasX, canvasY): 相对于 <canvas> 左上角的坐标; * (x, y): 相对于整个画布的坐标, 与 model 的 x, y 是同一维度的。 */ e.canvasX = e.x / pixelRatio; e.canvasY = e.y / pixelRatio; let point = { x: e.canvasX, y: e.canvasY }; if (isViewportChanged(graph.get('group').getMatrix())) { point = graph.getPointByCanvas(e.canvasX, e.canvasY); } e.x = point.x; e.y = point.y; // 事件currentTarget是graph e.currentTarget = graph; if (target === canvas) { if (eventType === 'mousemove') { self._handleMouseMove(e, 'canvas'); } e.target = canvas; e.item = null; graph.emit(eventType, e); graph.emit('canvas:' + eventType, e); return; } const itemShape = getItemRoot(target); if (!itemShape) { graph.emit(eventType, e); return; } const item = itemShape.get('item'); if (item.destroyed) { return; } const type = item.getType(); // 事件target是触发事件的Shape实例,, item是触发事件的item实例 e.target = target; e.item = item; graph.emit(eventType, e); // g的事件会冒泡,如果target不是canvas,可能会引起同个节点触发多次,需要另外判断 if (eventType === 'mouseenter' || eventType === 'mouseleave' || eventType === 'dragenter' || eventType === 'dragleave') { return; } graph.emit(type + ':' + eventType, e); if (eventType === 'dragstart') { self.dragging = true; } if (eventType === 'dragend') { self.dragging = false; } if (eventType === 'mousemove') { self._handleMouseMove(e, type); } } _onExtendEvents(e) { this.graph.emit(e.type, e); } _onWheelEvent(e) { if (Util.isNil(e.wheelDelta)) { e.wheelDelta = -e.detail; } this.graph.emit('wheel', e); } _handleMouseMove(e, type) { const self = this; const canvas = this.graph.get('canvas'); const item = e.target === canvas ? null : e.item; const preItem = this.preItem; // 避免e的type与触发的事件不同 e = Util.cloneEvent(e); // 从前一个item直接移动到当前item,触发前一个item的leave事件 if (preItem && preItem !== item && !preItem.destroyed) { e.item = preItem; self._emitCustomEvent(preItem.getType(), 'mouseleave', e); if (self.dragging) { self._emitCustomEvent(preItem.getType(), 'dragleave', e); } } // 从一个item或canvas移动到当前item,触发当前item的enter事件 if (item && preItem !== item) { e.item = item; self._emitCustomEvent(type, 'mouseenter', e); if (self.dragging) { self._emitCustomEvent(type, 'dragenter', e); } } this.preItem = item; } _emitCustomEvent(itemType, type, e) { e.type = type; this.graph.emit(itemType + ':' + type, e); } destroy() { const graph = this.graph; const canvasHandler = this.canvasHandler; const canvas = graph.get('canvas'); Util.each(EVENTS, event => { canvas.off(event, canvasHandler); }); Util.each(this.extendEvents, event => { event.remove(); }); } } module.exports = Event;