Skip to content

Commit

Permalink
Fix 1641 (#1642)
Browse files Browse the repository at this point in the history
* fix: support shadowRoot #1641

* chore: commit changeset

* chore: remove gui from test cases for now
  • Loading branch information
xiaoiver committed Mar 18, 2024
1 parent 0bb1bbe commit 10397c1
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 35 deletions.
6 changes: 6 additions & 0 deletions .changeset/tasty-pigs-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@antv/g-plugin-svg-picker': patch
'@antv/g-lite': patch
---

Support shadowRoot when picking.
7 changes: 3 additions & 4 deletions __tests__/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as lil from 'lil-gui';
import { runtime, Canvas, CanvasEvent } from '../packages/g';
import { Renderer as CanvasRenderer } from '../packages/g-canvas';
import { Renderer as CanvaskitRenderer } from '../packages/g-canvaskit';
Expand Down Expand Up @@ -209,10 +208,10 @@ function createSpecRender(object) {
window.__g_instances__ = [canvas];

// GUI
const gui = new lil.GUI({ autoPlace: false });
$div.appendChild(gui.domElement);
// const gui = new lil.GUI({ autoPlace: false });
// $div.appendChild(gui.domElement);

await generate({ canvas, renderer, container: $div, gui });
await generate({ canvas, renderer, container: $div });

if (
selectRenderer.value === 'canvas' &&
Expand Down
1 change: 1 addition & 0 deletions jest.node.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ module.exports = {
globalSetup: './scripts/jest/setup.js',
globalTeardown: './scripts/jest/teardown.js',
testEnvironment: './scripts/jest/environment.js',
testPathIgnorePatterns: ['<rootDir>/__tests__/main.ts'],
};
20 changes: 6 additions & 14 deletions packages/g-lite/src/plugins/EventPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,12 @@ export class EventPlugin implements RenderingPlugin {
const $element =
this.context.contextService.getDomElement() as HTMLCanvasElement;

let outside = 'outside';
try {
outside =
$element &&
nativeEvent.target &&
nativeEvent.target !== $element &&
$element.contains &&
!$element.contains(nativeEvent.target as Node)
? 'outside'
: '';
} catch (e) {
// nativeEvent.target maybe not Node, such as Window
// @see https://github.com/antvis/G/issues/1235
}
const isNativeEventFromCanvas =
this.context.eventService.isNativeEventFromCanvas(
$element,
nativeEvent,
);
const outside = !isNativeEventFromCanvas ? 'outside' : '';
const normalizedEvents = this.normalizeToPointerEvent(
nativeEvent,
canvas,
Expand Down
31 changes: 22 additions & 9 deletions packages/g-lite/src/services/EventService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import EventEmitter from 'eventemitter3';
import { mat4, vec3 } from 'gl-matrix';
import type { CanvasContext, GlobalRuntime } from '..';
import type { CanvasContext, GlobalRuntime, InteractivePointerEvent } from '..';
import type { HTML } from '../display-objects';
import type { FederatedEvent } from '../dom/FederatedEvent';
import { FederatedMouseEvent } from '../dom/FederatedMouseEvent';
Expand Down Expand Up @@ -709,10 +709,16 @@ export class EventService {
* whether the native event trigger came from Canvas,
* should account for HTML shape
*/
private isNativeEventFromCanvas(event: FederatedEvent) {
const $el = this.context.contextService.getDomElement();

const target = event.nativeEvent?.target;
isNativeEventFromCanvas(
$el: HTMLCanvasElement,
nativeEvent: InteractivePointerEvent,
) {
let target = nativeEvent?.target as Element;
// Get event target inside a web component.
// @see https://stackoverflow.com/questions/57963312/get-event-target-inside-a-web-component
if (target?.shadowRoot) {
target = nativeEvent.composedPath()[0] as Element;
}

if (target) {
// from <canvas>
Expand All @@ -726,8 +732,8 @@ export class EventService {
}
}

if (event.nativeEvent.composedPath) {
return event.nativeEvent.composedPath().indexOf($el as EventTarget) > -1;
if (nativeEvent?.composedPath) {
return nativeEvent.composedPath().indexOf($el as EventTarget) > -1;
}

// account for Touch
Expand Down Expand Up @@ -779,10 +785,13 @@ export class EventService {
event.originalEvent = from;

const existedHTML = this.getExistedHTML(event);
const $el =
this.context.contextService.getDomElement() as HTMLCanvasElement;
event.target =
target ??
(existedHTML ||
(this.isNativeEventFromCanvas(event) && this.pickTarget(event)) ||
(this.isNativeEventFromCanvas($el, event.nativeEvent) &&
this.pickTarget(event)) ||
fallbackTarget);

if (typeof type === 'string') {
Expand All @@ -802,9 +811,13 @@ export class EventService {
event.nativeEvent = from.nativeEvent;
event.originalEvent = from;
const existedHTML = this.getExistedHTML(event);

const $el =
this.context.contextService.getDomElement() as HTMLCanvasElement;
event.target =
existedHTML ||
(this.isNativeEventFromCanvas(event) && this.pickTarget(event));
(this.isNativeEventFromCanvas($el, event.nativeEvent) &&
this.pickTarget(event));
return event;
}

Expand Down
20 changes: 12 additions & 8 deletions packages/g-plugin-svg-picker/src/SVGPickerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class SVGPickerPlugin implements RenderingPlugin {

private pick(
svgElementMap: WeakMap<SVGElement, DisplayObject>,
doc: Document,
doc: Document | ShadowRoot,
result: PickingResult,
) {
const {
Expand All @@ -55,14 +55,18 @@ export class SVGPickerPlugin implements RenderingPlugin {
clientX,
clientY,
)) {
const target = svgElementMap.get(element as SVGElement);
// don't need to account for `visibility` since DOM API already does
if (target && target.isInteractive()) {
targets.push(target);
if (element.shadowRoot && element.shadowRoot !== doc) {
return this.pick(svgElementMap, element.shadowRoot, result);
} else {
const target = svgElementMap.get(element as SVGElement);
// don't need to account for `visibility` since DOM API already does
if (target && target.isInteractive()) {
targets.push(target);

if (topmost) {
result.picked = targets;
return result;
if (topmost) {
result.picked = targets;
return result;
}
}
}
}
Expand Down

0 comments on commit 10397c1

Please sign in to comment.