logo

G

  • Tutorials
  • API
  • Examples
  • Plugins
  • Productsantv logo arrow
  • 6.1.26
  • Canvas
    • Introduction
    • Options
    • Built-in objects
    • Coordinate system
    • Scenegraph & Lifecycle
    • Event
    • OffscreenCanvas & Server-side Rendering
    • CustomElementRegistry
    • Frequently Asked Questions
  • Renderer
    • Introduction
    • Canvas Renderer
    • Canvaskit Renderer
    • SVG Renderer
    • WebGL Renderer
    • WebGPU Renderer
    • Custom Renderer
  • Camera
    • Introduction
    • Camera Parameters
    • Camera action
    • Camera animation
  • Event
    • Introduction
    • Event Object
    • Gesture & Drag'n'Drop
    • Frequently Asked Questions
  • Animation
    • Web Animations API
    • Lottie
  • Basic Shapes
    • Basic Concepts
    • DisplayObject
    • Group
    • Text
    • Circle
    • Ellipse
    • Rect
    • Image
    • Line
    • Polygon
    • Polyline
    • Path
    • HTML
  • Style System
    • Introduction
    • CSS Typed OM
    • Inheritance
    • CSS Properties & Values API
    • CSS Layout API
    • Pattern
    • Gradient
  • 3D
    • 材质
    • 几何
    • Mesh
    • 光源
    • 雾
    • 交互
  • Built-in Objects
    • EventTarget
    • Node
    • Element
    • Document
    • MutationObserver
    • Utils
  • GPGPU
    • Introduction
    • Programming Model
    • Kernel API
    • Principles of classical GPGPU implementation
    • webgpu-graph
  • Declarative programming
    • 使用 Web Components
  • Devtools
    • G 开发者工具
    • 内置的渲染统计信息
    • 第三方开发调试工具

Frequently Asked Questions

Previous
Gesture & Drag'n'Drop
Next
Web Animations API

Resource

Ant Design
Galacea Effects
Umi-React Application Framework
Dumi-Component doc generator
ahooks-React Hooks Library

Community

Ant Financial Experience Tech
seeconfSEE Conf-Experience Tech Conference

Help

GitHub
StackOverflow

more productsMore Productions

Ant DesignAnt Design-Enterprise UI design language
yuqueYuque-Knowledge creation and Sharing tool
EggEgg-Enterprise-class Node development framework
kitchenKitchen-Sketch Tool set
GalaceanGalacean-Interactive solution
xtechLiven Experience technology
© Copyright 2025 Ant Group Co., Ltd..备案号:京ICP备15032932号-38

Loading...

The problem of 'this' within the event listener

Refer to https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#the_value_of_this_within_the_handler

Inside the event listener this should point to the same as e.currentTarget. However, if the arrow function is used, the context will be lost:

circle.addEventListener('mouseenter', function (e) {
console.log(this); // circle
console.log(e.currentTarget === this); // true
});
circle.addEventListener('mouseleave', () => {
console.log(this); // undefined
});

mouseenter/leave won't bubble up

https://developer.mozilla.org/zh-CN/docs/Web/API/Element/mouseenter_event

mouseenter does not bubble, while mouseover does. Similarly mouseleave does not bubble, while mouseout does.

Hit testing

The event system only responds to events within the Canvas canvas. For example, when mousemove is listened to, moving outside of the canvas to other areas of the page does not trigger the event handler. The target property of the event object returns Document when picking up a blank area of the canvas (without hitting any visible graphics).

canvas.addEventListener('mousemove', (e) => {
if (e.target.nodeName === 'document') {
// move on empty area
}
});

Event Trigger Sequence

Some built-in events have an order of firing, for example, the click event will be fired after the pointerdown and pointerup events. In this process, it is possible that the target of the pointerdown and pointerup events may not match. For example, if you press the mouse on one graph, move to another graph and then lift the mouse, we will trigger the click event on an ancestor node that is common to both targets (e.g. the root of the scene graph document.documentElement).

This can be tried in this example.

Disable default page scrolling behavior in Chrome

Sometimes we need to disable the default scrolling behavior of a page, for example when implementing a zoom class. Disabling the default behavior can be done with preventDefault, but the following code will not work in Chrome and the page will still scroll.

canvas.addEventListener('wheel', (e) => {
e.preventDefault();
});

The reason for this problem is that G added the passive: true configuration item when listening to the wheel event of the canvas event.

// $el is the DOM element, <canvas> in g-canvas/webgl while <svg> in g-svg
$el.addEventListener('wheel', onPointerWheel, {
passive: true,
capture: true,
});

For more information about Passive event handlers, please refer to this article from https://zhuanlan.zhihu.com/p/24555031. The short answer is that this option improves the browser's scrolling smoothness by telling the browser in advance that "I won't block your default scrolling behavior".

Now back to our question, if the user does need to disable the default scrolling behavior, a non-Passive event handler can be manually added to the DOM node of the canvas, g-plugin-control plugin does this. How to get the DOM node of the canvas can be done using getDomElement.

canvas
.getContextService()
.getDomElement() // g-canvas/webgl 为 <canvas>,g-svg 为 <svg>
.addEventListener(
'wheel',
(e) => {
e.preventDefault();
},
{ passive: false },
);

Other Events

Most of the other native events, especially keyboard and clipboard events that need to be bound to window/document, have no special usage in G. You can directly refer to the related events documentation.

Disable right-click menu

Sometimes we want to disable the browser's default right-click menu, so we can disable the default behavior in the contextmenu event handler with the preventDefault() method to disable the default behavior. To get the DOM node of the canvas you can use getDomElement.

canvas
.getContextService()
.getDomElement() // g-canvas/webgl 为 <canvas>,g-svg 为 <svg>
.addEventListener('contextmenu', (e) => {
e.preventDefault();
});

Note that since the default behavior of the rightup / down events is not to pop up the system menu, the following writeup is not valid.

// wrong
canvas.addEventListener('rightup', (e) => {
e.preventDefault();
});

KeyboardEvent

Use KeyboardEvent directly.

window.addEventListener('keydown', () => {}, false);

However, we have not yet implemented A11y-related features, such as using tabs to toggle selection between shapes within the canvas.

ClipboardEvent

Use ClipboardEvent directly.

FocusEvent

We don't have a built-in focus event like focus/blur, so the following code is not valid.

circle.addEventListener('focus', () => {});
circle.addEventListener('blur', () => {});

Focus-related functions can be implemented through events such as click/mouseenter/mouseleave. example

Doubleclick

Due to the need to be as compatible as possible with PC and mobile events, we do not listen to the native dblclick event, but to the pointerdown property by listening to pointerdown and pointerup, the number of clicks within a certain time interval (200ms) is recorded in the detail attribute, so that it is possible to distinguish between a click and a double click.

canvas.addEventListener('click', (e) => {
if (e.detail === 2) {
// dbclick
} else if (e.detail === 1) {
// click
}
});

Compatible API

The following way of writing delegates in event names is supported in older versions, in the format [delegated-graphic name]:[event-name], example.

// Listen for click events bubbling up on all graphs with the name node
graph.on('node:click', () => {});
// or
graph.addEventListener('click', (e) => {
if (e.target.name === 'node') {
}
});

Interaction with other plugins

Event Binding/Unbinding Plugin

As mentioned before, event binding is not done in the core event system, it should be left to the corresponding rendering environment plugins. For example, g-plugin-dom-interaction which uses DOM API to bind/unbind, other environments such as applets should write their own plugins.

In this class of plugins, we need to complete the binding in init and the unbinding in destroy. When implementing the binding, multiple (if any) native events in that rendering environment need to be mapped to G's standard event handlers.

// g-plugin-dom-interaction
const onPointerDown = (ev: InteractivePointerEvent) => {
renderingService.hooks.pointerDown.call(ev);
};
renderingService.hooks.init.tap(DOMInteractionPlugin.tag, () => {
// using native DOM API
$el.addEventListener(
'pointerdown', // native event
onPointerDown,
true,
);
// If mobile support is required
if (supportsTouchEvents) {
$el.addEventListener('touchstart', onPointerDown, true);
}
// ...
});
renderingService.hooks.destroy.tap(DOMInteractionPlugin.tag, () => {});

Picking Plugin

Different rendering environments use different pickup plugins for determining the EventTarget of native events.

  • g-plugin-canvas-picker Use mainly mathematical operations.
  • g-plugin-svg-picker Use SVG API.
  • g-plugin-device-renderer Use GPU-based methods.

A11y Plugin

In g-plugin-a11y, we listen to keyboard events for navigation.