Skip to content

Commit

Permalink
fix(g-svg): event should work when matrix is applied, close antvis#428
Browse files Browse the repository at this point in the history
  • Loading branch information
dengfuping committed Feb 26, 2020
1 parent a47eff5 commit 475afbb
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 11 deletions.
10 changes: 5 additions & 5 deletions packages/g-base/src/abstract/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ abstract class Container extends Element implements IContainer {
return canvas;
}

getShape(x: number, y: number): IShape {
getShape(x: number, y: number, ev: Event): IShape {
// 如果不支持拾取,则直接返回
if (!isAllowCapture(this)) {
return null;
Expand All @@ -267,21 +267,21 @@ abstract class Container extends Element implements IContainer {
// 将 x, y 转换成对应于 group 的局部坐标
v = this.invertFromMatrix(v);
if (!this.isClipped(v[0], v[1])) {
shape = this._findShape(children, v[0], v[1]);
shape = this._findShape(children, v[0], v[1], ev);
}
} else {
shape = this._findShape(children, x, y);
shape = this._findShape(children, x, y, ev);
}
return shape;
}

_findShape(children: IElement[], x: number, y: number) {
_findShape(children: IElement[], x: number, y: number, ev: Event) {
let shape = null;
for (let i = children.length - 1; i >= 0; i--) {
const child = children[i];
if (isAllowCapture(child)) {
if (child.isGroup()) {
shape = (child as IGroup).getShape(x, y);
shape = (child as IGroup).getShape(x, y, ev);
} else if ((child as IShape).isHit(x, y)) {
shape = child;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/g-base/src/event/event-contoller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ class EventController {
};

// 根据点获取图形,提取成独立方法,便于后续优化
_getShapeByPoint(point) {
return this.canvas.getShape(point.x, point.y);
_getShape(point, ev: Event) {
return this.canvas.getShape(point.x, point.y, ev);
}
// 获取事件的当前点的信息
_getPointInfo(ev) {
Expand All @@ -203,7 +203,7 @@ class EventController {
_triggerEvent(type, ev) {
const pointInfo = this._getPointInfo(ev);
// 每次都获取图形有一定成本,后期可以考虑进行缓存策略
const shape = this._getShapeByPoint(pointInfo);
const shape = this._getShape(pointInfo, ev);
const method = this[`_on${type}`];
let leaveCanvas = false;
if (method) {
Expand Down Expand Up @@ -343,7 +343,7 @@ class EventController {
}
this.dragging = false;
// drag 完成后,有可能 draggingShape 已经移动到了当前位置,所以不能直接取当前图形
const shape = this._getShapeByPoint(pointInfo);
const shape = this._getShape(pointInfo, event);
// 拖拽完成后,进行 enter,leave 的判定
if (shape !== draggingShape) {
this._emitMouseoverEvents(event, pointInfo, draggingShape, shape);
Expand Down
3 changes: 2 additions & 1 deletion packages/g-base/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,10 @@ export interface IContainer extends IElement {
* 根据 x,y 获取对应的图形
* @param {number} x x 坐标
* @param {number} y y 坐标
* @param {Event} 浏览器事件对象
* @returns 添加的图形分组
*/
getShape(x: number, y: number): IShape;
getShape(x: number, y: number, ev: Event): IShape;

/**
* 添加图形元素,已经在外面构造好的类
Expand Down
16 changes: 15 additions & 1 deletion packages/g-svg/src/canvas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AbstractCanvas } from '@antv/g-base';
import { AbstractCanvas, IShape } from '@antv/g-base';
import { ChangeType } from '@antv/g-base/lib/types';
import { IElement } from './interfaces';
import { SHAPE_TO_TAGS } from './constant';
import { drawChildren } from './util/draw';
import { setTransform, setClip } from './util/svg';
import { sortDom } from './util/dom';
Expand All @@ -27,6 +28,19 @@ class Canvas extends AbstractCanvas {
return Group;
}

// 覆盖 Container 中通过遍历的方式获取 shape 对象的逻辑,直接走 SVG 的 dom 拾取即可
getShape(x: number, y: number, ev: Event): IShape {
let target = <Element>ev.target || <Element>ev.srcElement;
if (!SHAPE_TO_TAGS[target.tagName]) {
let parent = <Element>target.parentNode;
while (parent && !SHAPE_TO_TAGS[parent.tagName]) {
parent = <Element>parent.parentNode;
}
target = parent;
}
return this.find((child) => child.get('el') === target) as IShape;
}

// 复写基类的方法生成标签
createDom() {
const element = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
Expand Down
46 changes: 46 additions & 0 deletions packages/g-svg/tests/bugs/issue-428-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// const expect = require('chai').expect;
// import Canvas from '../../src/canvas';
// import { simulateMouseEvent, getClientPoint } from '../util';

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

// describe('#428', () => {
// const canvas = new Canvas({
// container: dom,
// width: 400,
// height: 400,
// });

// const el = canvas.get('el');

// it('event should work when matrix is applied', () => {
// const group = canvas.addGroup();
// const circle = group.addShape('circle', {
// attrs: {
// x: 100,
// y: 100,
// r: 50,
// fill: 'red',
// },
// });
// circle.translate(100, 0);

// let clickCalled = false;
// circle.on('click', () => {
// clickCalled = true;
// });

// const { clientX, clientY } = getClientPoint(canvas, 200, 100);
// simulateMouseEvent(el, 'mousedown', {
// clientX,
// clientY,
// });
// simulateMouseEvent(el, 'mouseup', {
// clientX,
// clientY,
// });
// expect(clickCalled).eqls(true);
// });
// });
12 changes: 12 additions & 0 deletions packages/g-svg/tests/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function simulateMouseEvent(dom, type, cfg) {
const event = new MouseEvent(type, cfg);
dom.dispatchEvent(event);
}

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

0 comments on commit 475afbb

Please sign in to comment.