Skip to content

Commit

Permalink
fix(g-svg): mouseenter and mouseleave should be effective, close antv…
Browse files Browse the repository at this point in the history
  • Loading branch information
dengfuping committed Oct 21, 2019
1 parent f2d64d1 commit 2b9b830
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
31 changes: 30 additions & 1 deletion packages/g-base/src/event/event-contoller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/
import GraphEvent from './graph-event';
import { ICanvas, IShape, IBase } from '../interfaces';
import { each } from '../util/util';
import { each, isArray } from '../util/util';
const TIME_INTERVAL = 120; // 判断拖拽和点击
const CLICK_OFFSET = 40;
const DELEGATION_SPLIT = ':';
Expand All @@ -28,6 +28,15 @@ const EVENTS = [
'contextmenu',
];

const EVENT_MAP = {
mouseenter: 'mouseleave',
dragenter: 'dragleave',
mouseover: ['mouseout', 'mouseleave'], // 需要按照特定顺序,先触发 mouseout 事件,再触发 mouseleave 事件
mouseleave: 'mouseenter',
dragleave: 'dragenter',
mouseout: ['mouseover', 'mouseenter'], // 需要按照特定顺序,先触发 mouseover 事件,再触发 mouseenter 事件
};

// 是否元素的父容器
function isParent(container, shape) {
// 所有 shape 都是 canvas 的子元素
Expand Down Expand Up @@ -194,6 +203,16 @@ class EventController {
const preShape = this.currentShape;
// 如果进入、移出画布时存在图形,则要分别出发事件
if (type === 'mouseenter' || type === 'dragenter' || type === 'mouseover') {
// 从图形进入画布,preShape 上的事件最先触发
if (preShape) {
if (isArray(EVENT_MAP[type])) {
each(EVENT_MAP[type], (item) => {
this._emitEvent(item, event, pointInfo, null, preShape, null); // 图形 => 画布
});
} else {
this._emitEvent(EVENT_MAP[type], event, pointInfo, null, preShape, null); // 图形 => 画布
}
}
this._emitEvent(type, event, pointInfo, null, null, shape); // 先进入画布
if (shape) {
this._emitEvent(type, event, pointInfo, shape, null, shape); // 再触发图形的事件
Expand All @@ -203,6 +222,16 @@ class EventController {
this._emitEvent(type, event, pointInfo, preShape, preShape, null); // 先触发图形的事件
}
this._emitEvent(type, event, pointInfo, null, preShape, null); // 再触发离开画布事件
// 从画布进入图形,shape 上的事件最后触发
if (shape) {
if (isArray(EVENT_MAP[type])) {
each(EVENT_MAP[type], (item) => {
this._emitEvent(item, event, pointInfo, shape, null, shape);
});
} else {
this._emitEvent(EVENT_MAP[type], event, pointInfo, shape, null, shape);
}
}
} else {
this._emitEvent(type, event, pointInfo, shape, null, null); // 一般事件中不需要考虑 from, to
}
Expand Down
60 changes: 60 additions & 0 deletions packages/g-svg/tests/bugs/issue-205-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const expect = require('chai').expect;
import Canvas from '../../src/canvas';

export function simulateMouseEvent(dom, type, cfg) {
const event = new MouseEvent(type, cfg);
dom.dispatchEvent(event);
}

const dom = document.createElement('div');
document.body.appendChild(dom);
dom.id = 'c1';

describe('#205', () => {
const canvas = new Canvas({
container: dom,
width: 500,
height: 500,
});
const el = canvas.get('el');

function getClientPoint(x, y) {
const point = canvas.getClientByPoint(x, y);
return {
clientX: point.x,
clientY: point.y,
};
}

it('mouseenter and mouseleave should be effective', () => {
const group = canvas.addGroup();
const shape = group.addShape('circle', {
attrs: {
x: 100,
y: 100,
r: 40,
fill: 'red',
},
});
let flag = 0;

shape.on('mouseenter', () => {
flag = 1;
});
shape.on('mouseleave', () => {
flag = 2;
});

const { clientX, clientY } = getClientPoint(100, 100);
simulateMouseEvent(el, 'mouseenter', {
clientX,
clientY,
});
expect(flag).eqls(1);
simulateMouseEvent(el, 'mouseleave', {
clientX: clientX + 50,
clientY: clientX + 50,
});
expect(flag).eqls(2);
});
});

0 comments on commit 2b9b830

Please sign in to comment.