Skip to content

Commit

Permalink
fix(event): emit events for extended shape (#5290)
Browse files Browse the repository at this point in the history
  • Loading branch information
pearmini committed Jul 10, 2023
1 parent 57246a1 commit 873bec7
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
32 changes: 32 additions & 0 deletions __tests__/integration/api-chart-on-text-click.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { chartOnTextClick as render } from '../plots/api/chart-on-text-click';
import { createDOMGCanvas } from './utils/createDOMGCanvas';
import { dispatchFirstElementEvent, createPromise } from './utils/event';
import './utils/useSnapshotMatchers';
import { ChartEvent } from '../../src';

Check warning on line 5 in __tests__/integration/api-chart-on-text-click.spec.ts

View workflow job for this annotation

GitHub Actions / build

`../../src` import should occur before import of `./utils/createDOMGCanvas`

describe('chart.on', () => {
const canvas = createDOMGCanvas(640, 480);
const { finished, chart } = render({ canvas });

chart.off();

it('chart.on("text:click", callback) should provide datum for item element', async () => {
await finished;
const [fired, resolve] = createPromise();
chart.on(`text:${ChartEvent.CLICK}`, resolve);
dispatchFirstElementEvent(canvas, 'click', { detail: 1 });
await fired;
});

it('chart.on("element:click", callback) should provide datum for item element', async () => {
await finished;
const [fired, resolve] = createPromise();
chart.on(`element:${ChartEvent.CLICK}`, resolve);
dispatchFirstElementEvent(canvas, 'click', { detail: 1 });
await fired;
});

afterAll(() => {
canvas?.destroy();
});
});
24 changes: 24 additions & 0 deletions __tests__/plots/api/chart-on-text-click.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Chart } from '../../../src';

export function chartOnTextClick(context) {
const { container, canvas } = context;

const chart = new Chart({ theme: 'classic', container, canvas });

chart.text().style({
x: 290, // 像素坐标
y: 200, // 像素坐标
text: 'hello',
textAlign: 'center',
fontSize: 60,
textBaseline: 'middle',
});

chart.on('element:click', () => console.log('click element'));

chart.on('text:click', () => console.log('click text'));

const finished = chart.render();

return { chart, finished };
}
1 change: 1 addition & 0 deletions __tests__/plots/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ export { chartEmitItemTooltipHideContent } from './chart-emit-item-tooltip-hide-
export { chartEmitClickTooltip } from './chart-emit-click-tooltip';
export { chartChangeDataLegend } from './chart-change-data-legend';
export { chartTooltipMultiChart } from './chart-tooltip-multi-chart';
export { chartOnTextClick } from './chart-on-text-click';
19 changes: 15 additions & 4 deletions src/interaction/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export function dataOf(element, view) {
return selectedMark.data[index];
}

// For extended shape.
function maybeElementRoot(node) {
if (node.className === 'element') return node;
let root = node.parent;
while (root && root.className !== 'element') root = root.parent;
return root;
}

function bubblesEvent(eventType, view, emitter, predicate = (event) => true) {
return (e) => {
if (!predicate(e)) return;
Expand All @@ -26,17 +34,20 @@ function bubblesEvent(eventType, view, emitter, predicate = (event) => true) {
// There is no target for pointerupoutside event if out of canvas.
if (!target) return;

const { className: elementType, markType } = target;
const { className } = target;

// If target area is plot area, do not emit extra events.
if (elementType === 'plot') return;
if (className === 'plot') return;

// Emit wrapped events.
// If target is element or child of element.
const elementRoot = maybeElementRoot(target);
if (!elementRoot) return;
const { className: elementType, markType } = elementRoot;
if (elementType === 'element') {
const e1 = {
...e,
nativeEvent: true,
data: { data: dataOf(target, view) },
data: { data: dataOf(elementRoot, view) },
};
emitter.emit(`element:${eventType}`, e1);
emitter.emit(`${markType}:${eventType}`, e1);
Expand Down

0 comments on commit 873bec7

Please sign in to comment.