/** * @fileOverview The controller of chart's events * @author sima.zhang */ var Util = require('../../util'); function isSameShape(shape1, shape2) { if (Util.isNil(shape1) || Util.isNil(shape2)) { return false; } var shape1Origin = shape1.get('origin'); var shape2Origin = shape2.get('origin'); // hotfix: if both shapes have no data,just compare shapes. if (Util.isNil(shape1Origin) && Util.isNil(shape2Origin)) { return Util.isEqual(shape1, shape2); } return Util.isEqual(shape1Origin, shape2Origin); } function registerData(eventObj) { if (eventObj.shape && eventObj.shape.get('origin')) { eventObj.data = eventObj.shape.get('origin'); } } var EventController = /*#__PURE__*/function () { function EventController(cfg) { this.view = null; this.canvas = null; Util.assign(this, cfg); this._init(); } var _proto = EventController.prototype; _proto._init = function _init() { this.pixelRatio = this.canvas.get('pixelRatio'); }; _proto._getShapeEventObj = function _getShapeEventObj(ev) { return { x: ev.x / this.pixelRatio, y: ev.y / this.pixelRatio, target: ev.target, // canvas 元素 toElement: ev.event.toElement || ev.event.relatedTarget }; }; _proto._getShape = function _getShape(x, y) { var view = this.view; var container = view.get('canvas'); return container.getShape(x, y); }; _proto._getPointInfo = function _getPointInfo(ev) { var view = this.view; var point = { x: ev.x / this.pixelRatio, y: ev.y / this.pixelRatio }; var views = view.getViewsByPoint(point); point.views = views; return point; }; _proto._getEventObj = function _getEventObj(ev, point, views) { return { x: point.x, y: point.y, target: ev.target, // canvas 元素 toElement: ev.event.toElement || ev.event.relatedTarget, // 目标元素 views: views }; }; _proto.bindEvents = function bindEvents() { var canvas = this.canvas; canvas.on('mousedown', Util.wrapBehavior(this, 'onDown')); canvas.on('mousemove', Util.wrapBehavior(this, 'onMove')); canvas.on('mouseleave', Util.wrapBehavior(this, 'onOut')); canvas.on('mouseup', Util.wrapBehavior(this, 'onUp')); canvas.on('click', Util.wrapBehavior(this, 'onClick')); canvas.on('dblclick', Util.wrapBehavior(this, 'onClick')); canvas.on('touchstart', Util.wrapBehavior(this, 'onTouchstart')); canvas.on('touchmove', Util.wrapBehavior(this, 'onTouchmove')); canvas.on('touchend', Util.wrapBehavior(this, 'onTouchend')); }; _proto._triggerShapeEvent = function _triggerShapeEvent(shape, eventName, eventObj) { if (shape && shape.name && !shape.get('destroyed')) { var view = this.view; if (view.isShapeInView(shape)) { var name = shape.name + ':' + eventName; eventObj.view = view; eventObj.appendInfo = shape.get('appendInfo'); // appendInfo is defined by user view.emit(name, eventObj); var parent = view.get('parent'); if (parent) { // chart 上也需要抛出该事件,本期先不抛出 parent.emit(name, eventObj); } } } }; _proto.onDown = function onDown(ev) { var view = this.view; var eventObj = this._getShapeEventObj(ev); eventObj.shape = this.currentShape; registerData(eventObj); view.emit('mousedown', eventObj); this._triggerShapeEvent(this.currentShape, 'mousedown', eventObj); }; _proto.onMove = function onMove(ev) { var self = this; var view = self.view; var currentShape = self.currentShape; // 如果图形被销毁,则设置当前 shape 为空 if (currentShape && currentShape.get('destroyed')) { currentShape = null; self.currentShape = null; } var shape = self._getShape(ev.x, ev.y) || ev.currentTarget; var eventObj = self._getShapeEventObj(ev); eventObj.shape = shape; registerData(eventObj); view.emit('mousemove', eventObj); self._triggerShapeEvent(shape, 'mousemove', eventObj); if (currentShape && !isSameShape(currentShape, shape)) { var leaveObj = self._getShapeEventObj(ev); leaveObj.shape = currentShape; leaveObj.toShape = shape; registerData(leaveObj); self._triggerShapeEvent(currentShape, 'mouseleave', leaveObj); } if (shape && !isSameShape(currentShape, shape)) { var enterObj = self._getShapeEventObj(ev); enterObj.shape = shape; enterObj.fromShape = currentShape; registerData(enterObj); self._triggerShapeEvent(shape, 'mouseenter', enterObj); } self.currentShape = shape; var point = self._getPointInfo(ev); var preViews = self.curViews || []; if (preViews.length === 0 && point.views.length) { view.emit('plotenter', self._getEventObj(ev, point, point.views)); } // point.views 是指当前 view 或者子 view,不会取跟当前 view 同一层级的兄弟元素(view) if (preViews.length && point.views.length === 0) { view.emit('plotleave', self._getEventObj(ev, point, preViews)); } if (point.views.length) { eventObj = self._getEventObj(ev, point, point.views); eventObj.shape = shape; registerData(eventObj); view.emit('plotmove', eventObj); } self.curViews = point.views; }; _proto.onOut = function onOut(ev) { var self = this; var view = self.view; var point = self._getPointInfo(ev); var preViews = self.curViews || []; var evtObj = self._getEventObj(ev, point, preViews); // 只有没有padding 时,当前依然在 view 的 plotRange 情况下才会出现这个情况,保证 plotleave 触发 if (self.curViews && self.curViews.length !== 0 && (!evtObj.toElement || evtObj.toElement.tagName !== 'CANVAS')) { view.emit('plotleave', evtObj); self.curViews = []; // 清空 } }; _proto.onUp = function onUp(ev) { var view = this.view; var eventObj = this._getShapeEventObj(ev); eventObj.shape = this.currentShape; view.emit('mouseup', eventObj); this._triggerShapeEvent(this.currentShape, 'mouseup', eventObj); }; _proto.onClick = function onClick(ev) { var self = this; var view = self.view; var shape = self._getShape(ev.x, ev.y) || ev.currentTarget; var shapeEventObj = self._getShapeEventObj(ev); shapeEventObj.shape = shape; registerData(shapeEventObj); view.emit('click', shapeEventObj); self._triggerShapeEvent(shape, ev.type, shapeEventObj); self.currentShape = shape; var point = self._getPointInfo(ev); var views = point.views; if (!Util.isEmpty(views)) { var eventObj = self._getEventObj(ev, point, views); if (self.currentShape) { var _shape = self.currentShape; eventObj.shape = _shape; registerData(eventObj); // eventObj.data = shape.get('origin'); } if (ev.type === 'dblclick') { view.emit('plotdblclick', eventObj); view.emit('dblclick', shapeEventObj); } else { view.emit('plotclick', eventObj); } } }; _proto.onTouchstart = function onTouchstart(ev) { var view = this.view; var shape = this._getShape(ev.x, ev.y) || ev.currentTarget; var eventObj = this._getShapeEventObj(ev); eventObj.shape = shape; registerData(eventObj); view.emit('touchstart', eventObj); this._triggerShapeEvent(shape, 'touchstart', eventObj); this.currentShape = shape; }; _proto.onTouchmove = function onTouchmove(ev) { var view = this.view; var shape = this._getShape(ev.x, ev.y) || ev.currentTarget; var eventObj = this._getShapeEventObj(ev); eventObj.shape = shape; registerData(eventObj); view.emit('touchmove', eventObj); this._triggerShapeEvent(shape, 'touchmove', eventObj); this.currentShape = shape; }; _proto.onTouchend = function onTouchend(ev) { var view = this.view; var eventObj = this._getShapeEventObj(ev); eventObj.shape = this.currentShape; registerData(eventObj); view.emit('touchend', eventObj); this._triggerShapeEvent(this.currentShape, 'touchend', eventObj); }; _proto.clearEvents = function clearEvents() { var canvas = this.canvas; canvas.off('mousemove', Util.getWrapBehavior(this, 'onMove')); canvas.off('mouseleave', Util.getWrapBehavior(this, 'onOut')); canvas.off('mousedown', Util.getWrapBehavior(this, 'onDown')); canvas.off('mouseup', Util.getWrapBehavior(this, 'onUp')); canvas.off('click', Util.getWrapBehavior(this, 'onClick')); canvas.off('dblclick', Util.getWrapBehavior(this, 'onClick')); canvas.off('touchstart', Util.getWrapBehavior(this, 'onTouchstart')); canvas.off('touchmove', Util.getWrapBehavior(this, 'onTouchmove')); canvas.off('touchend', Util.getWrapBehavior(this, 'onTouchend')); }; return EventController; }(); module.exports = EventController;