Skip to content

Event Handling

G2 exposes a set of events for accessing the chart’s lifecycle and interaction information. G2 exports a ChartEvent type to define event types.

click event
import { Chart, ChartEvent } from '@antv/g2';

const chart = new Chart({
  container,
  canvas,
});

chart.options({
  type: 'interval',
  data: [
    { genre: 'Sports', sold: 275 },
    { genre: 'Strategy', sold: 115 },
    { genre: 'Action', sold: 120 },
    { genre: 'Shooter', sold: 350 },
    { genre: 'Other', sold: 150 },
  ],
  encode: {
    x: 'genre',
    y: 'sold',
    color: 'genre',
  },
  axis: {
    x: { animate: false },
    y: { animate: false },
  },
});

chart.on('interval:click', (e) => {
  console.log(e.data.data); // Display clicked data
});

chart.on('element:click', (e) => {
  console.log(e.data.data); // Display clicked data
});

chart.render();

Lifecycle Events

To access the chart’s lifecycle information, you can use the following approach:

chart.on(ChartEvent.AFTER_RENDER, (ev) => {
  console.log(ev);
});

G2 currently provides the following lifecycle events:

Event Name Description
ChartEvent.BEFORE_RENDER Before render
ChartEvent.BEFORE_PAINT Before paint
ChartEvent.AFTER_PAINT After paint
ChartEvent.AFTER_RENDER After render
ChartEvent.BEFORE_CHANGE_DATA Before data change
ChartEvent.AFTER_CHANGE_DATA After data change
ChartEvent.BEFORE_CLEAR Before canvas clear
ChartEvent.AFTER_CLEAR After canvas clear
ChartEvent.BEFORE_DESTROY Before canvas destroy
ChartEvent.AFTER_DESTROY After canvas destroy
ChartEvent.BEFORE_CHANGE_SIZE Before canvas size change
ChartEvent.AFTER_CHANGE_SIZE After canvas size change
  • Before render: G2 begins processing data, performing layout, drawing graphics, etc.
  • Before paint: Data processing, layout, and drawing graphics are complete, but actual painting has not yet occurred.
  • After paint: G2 has completed all painting operations, but animations may still be running. The chart is fully rendered after animations complete.
  • After render: G2 has completed all painting operations, including animations.
  • After canvas clear: The chart in the container has been cleared, but the G2 instance still exists and can be used.
  • After canvas destroy: The G2 instance has been destroyed and can no longer be used.

Interaction Events

To access the chart’s interaction information, you can use the following approaches:

  • Listen to global element events
chart.on(`element:${ChartEvent.EventType}`, (ev) => {
  console.log(ev);
});
  • Listen to specific element events
chart.on(`${markType}:${ChartEvent.EventType}`, (ev) => {
  console.log(ev);
});

// For example, listen to click events on bars in a bar chart
chart.on(`interval:${ChartEvent.CLICK}`, (ev) => {
  console.log(ev);
});
  • Listen to plot area events
chart.on('plot:click', (event) => console.log(event));
  • Listen to global component events
chart.on('component:click', (event) => console.log(event));
  • Listen to global label events
chart.on('label:click', (event) => console.log(event));

Click Events

Event Name Description Callback Parameter
ChartEvent.CLICK Click Event
ChartEvent.DBLCLICK Double click Event

Pointer Events

Event Name Description Callback Parameter
ChartEvent.POINTER_TAP Event
ChartEvent.POINTER_DOWN When pointer is pressed down Event
ChartEvent.POINTER_UP When pointer is released Event
ChartEvent.POINTER_OVER When pointer enters the target element Event
ChartEvent.POINTER_OUT When pointer leaves the target element Event
ChartEvent.POINTER_MOVE When pointer changes coordinates Event
ChartEvent.POINTER_ENTER When pointer enters target element or its children Event
ChartEvent.POINTER_LEAVE When pointer leaves target element or its children Event
ChartEvent.POINTER_UPOUTSIDE Event

Drag Events

To listen to drag events, you need to set the draggable and droppable properties:

chart.options({
  type: 'interval',
  style: {
    draggable: true,
    droppable: true,
  },
});
Event Name Description Callback Parameter
ChartEvent.DRAG_START When dragging starts Event
ChartEvent.DRAG During dragging Event
ChartEvent.DRAG_END When dragging completes Event
ChartEvent.DRAG_ENTER When element is dragged into the target element Event
ChartEvent.DRAG_LEAVE When element is dragged out of the target element Event
ChartEvent.DRAG_OVER When element is dragged over the target element Event
ChartEvent.DROP When element is dropped into the target element Event

Fine-grained Control with className

G2 provides standardized className for various component elements in the chart, enabling more fine-grained event listening and style control.

:::warning{title=Important Note} For interaction events on components like legends and axes, it is highly recommended to use G2’s high-level interaction events rather than directly manipulating DOM elements. This provides a more stable and semantically clear event handling mechanism. Related interaction documentation: Legend Filter, Legend Highlight. :::

For components like legends and axes, the following approaches are recommended:

Approach 1: Using High-level Interaction Events (Recommended ⭐⭐⭐⭐⭐)

import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  autoFit: true,
});

chart.options({
  type: 'interval',
  data: [
    { genre: 'Sports', sold: 275 },
    { genre: 'Strategy', sold: 115 },
    { genre: 'Action', sold: 120 },
    { genre: 'Shooter', sold: 350 },
    { genre: 'Other', sold: 150 },
  ],
  encode: {
    x: 'genre',
    y: 'sold',
    color: 'genre',
  },
});

chart.render();

// Recommended: Use high-level interaction events
chart.on('legend:filter', (e) => {
  const { nativeEvent, data } = e;
  if (!nativeEvent) return; // Filter programmatic events

  console.log('✅ Legend filter event:', data);
  console.log('   - Channel:', data.channel);
  console.log('   - Current selected values:', data.values);
});

chart.on('legend:reset', (e) => {
  const { nativeEvent } = e;
  if (!nativeEvent) return;
  console.log('✅ Legend reset (select all)');
});

Approach 2: Listening to Specific Child Element Events (Suitable for simple custom interactions)

For custom interaction logic, you can listen to component child element events:

import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  autoFit: true,
});

chart.options({
  type: 'interval',
  data: [
    { genre: 'Sports', sold: 275 },
    { genre: 'Strategy', sold: 115 },
    { genre: 'Action', sold: 120 },
    { genre: 'Shooter', sold: 350 },
    { genre: 'Other', sold: 150 },
  ],
  encode: {
    x: 'genre',
    y: 'sold',
    color: 'genre',
  },
});

chart.render();

// Listen to legend label and marker clicks
const handleLegendClick = (event, source) => {
  // Method 1: Get complete data via parent container (recommended)
  const item = event.target.parentNode.parentNode; // marker/label -> group -> item
  if (item && item.__data__) {
    // Find the actual legend component (className includes 'legend-category')
    let legend = item.parentNode;
    while (legend && !legend.className.includes('legend-category')) {
      legend = legend.parentNode;
      if (!legend) return;
    }

    if (legend && legend.attributes && legend.attributes.data) {
      const { data } = legend.attributes;
      const { index } = item.__data__;
      const itemData = data[index];
      console.log(`✅ Clicked ${source}:`, itemData); // {id, label, color}
      console.log(`   - ID: ${itemData.id}`);
      console.log(`   - Label: ${itemData.label}`);
      console.log(`   - Color: ${itemData.color}`);
    }
  }

  // Method 2: Get partial information from target.attributes
  if (source === 'label') {
    console.log('   - Text:', event.target.attributes.text);
  } else if (source === 'marker') {
    console.log('   - Color:', event.target.attributes.fill);
  }
};

chart.on('g2-legend-marker:click', (e) => handleLegendClick(e, 'marker'));
chart.on('g2-legend-label:click', (e) => handleLegendClick(e, 'label'));

Approach 3: Direct Canvas DOM Manipulation (Most flexible, for fully customized scenarios)

Use only when complete customization is needed:

chart.on('afterrender', () => {
  const { canvas } = chart.getContext();
  const { document } = canvas;
  const items = document.getElementsByClassName('g2-legend-item');

  items.forEach((item) => {
    // Utilize event bubbling: clicks on child elements bubble to container
    item.addEventListener('click', () => {
      // Find the actual legend component
      let legend = item.parentNode;
      while (legend && !legend.className.includes('legend-category')) {
        legend = legend.parentNode;
        if (!legend) return;
      }

      if (legend && legend.attributes && legend.attributes.data) {
        const { data } = legend.attributes;
        const { index } = item.__data__;
        const itemData = data[index]; // {id, label, color}
        console.log('Legend item data:', itemData);
      }
    });
  });
});

Filtering Specific Component Events

Using className makes it easy to filter out events from certain components to avoid interference:

import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  autoFit: true,
});

chart.options({
  type: 'interval',
  data: [
    { genre: 'Sports', sold: 275 },
    { genre: 'Strategy', sold: 115 },
    { genre: 'Action', sold: 120 },
    { genre: 'Shooter', sold: 350 },
    { genre: 'Other', sold: 150 },
  ],
  encode: {
    x: 'genre',
    y: 'sold',
    color: 'genre',
  },
});

chart.render();

// Listen to plot clicks, but exclude legend clicks
chart.on('plot:click', (event) => {
  const className = event.target?.className || '';

  // Check if legend was clicked
  const isLegendClick = className.includes('legend');

  if (isLegendClick) {
    console.log('Legend clicked, ignoring plot:click event');
    return;
  }

  // Handle plot click logic
  console.log('Plot area clicked', event);
});

Controlling Element Styles with className

You can get specific elements via className and dynamically modify their styles:

import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  autoFit: true,
});

chart.options({
  type: 'interval',
  data: [
    { genre: 'Sports', sold: 275 },
    { genre: 'Strategy', sold: 115 },
    { genre: 'Action', sold: 120 },
    { genre: 'Shooter', sold: 350 },
    { genre: 'Other', sold: 150 },
  ],
  encode: {
    x: 'genre',
    y: 'sold',
    color: 'genre',
  },
});

chart.render().then(() => {
  const { canvas } = chart.getContext();
  const { document } = canvas;
  const legendItems = document.getElementsByClassName('g2-legend-item');

  // Modify the first legend item's style
  if (legendItems.length > 0) {
    const firstItem = legendItems[0];
    const firstMarker = firstItem.getElementsByClassName('g2-legend-marker')[0];
    const firstLabel = firstItem.getElementsByClassName('g2-legend-label')[0];

    // Add highlight style
    if (firstLabel) {
      firstLabel.style.fontWeight = 'bold';
      firstLabel.style.fill = 'orange';
      firstLabel.style.shadowColor = '#d3d3d3';
      firstLabel.style.shadowBlur = 10;
      firstLabel.style.shadowOffsetX = 5;
      firstLabel.style.shadowOffsetY = 5;
    }
  }
});

Finding Specific Elements by Content

Combining className with element attributes allows precise targeting of specific chart elements:

import { Chart } from '@antv/g2';

const chart = new Chart({
  container: 'container',
  autoFit: true,
});

chart.options({
  type: 'interval',
  data: [
    { genre: 'Sports', sold: 275 },
    { genre: 'Strategy', sold: 115 },
    { genre: 'Action', sold: 120 },
    { genre: 'Shooter', sold: 350 },
    { genre: 'Other', sold: 150 },
  ],
  encode: {
    x: 'genre',
    y: 'sold',
    color: 'genre',
  },
});

chart.render().then(() => {
  const { canvas } = chart.getContext();
  const { document } = canvas;
  const legendItems = document.getElementsByClassName('g2-legend-item');
  const targetText = 'Action';
  let targetItem = null;

  // Iterate through all legend labels to find target text
  for (let i = 0; i < legendItems.length; i++) {
    const labels = legendItems[i].getElementsByClassName('g2-legend-label');
    if (labels.length > 0) {
      const labelText = labels[0].getAttribute('text') || labels[0].textContent;
      if (labelText === targetText) {
        targetItem = legendItems[i];
        break;
      }
    }
  }

  if (targetItem) {
    console.log(`✅ Found target legend: "${targetText}"`);
    console.log('   className:', targetItem.className);
    console.log('   Can execute business logic: e.g., auto-focus, highlight, etc.');

    // Add background color and special styles to the target legend item

    console.log(`🎨 Adding special styles to legend "${targetText}"...`);

    // Get the legend item's background element
    const background = targetItem.getElementsByClassName(
      'g2-legend-background',
    )[0];
    const label = targetItem.getElementsByClassName('g2-legend-label')[0];
    const marker = targetItem.getElementsByClassName('g2-legend-marker')[0];

    // Modify background color
    if (background) {
      background.style.fill = '#FFF3E0'; // Light orange background
      background.style.fillOpacity = 0.8;
    }

    // Also modify label style
    if (label) {
      label.style.fill = '#FF6B00'; // Orange text
      label.style.fontWeight = 'bold';
    }
  }
});

Complete List of G2 Component className

Legend Components

className Description
g2-legend-title Legend title
g2-legend-item Category legend item container
g2-legend-background Category legend item background
g2-legend-marker Category legend item marker
g2-legend-label Category legend item label text
g2-legend-value Category legend item value
g2-legend-focus-icon Category legend item focus icon
g2-legend-ribbon Continuous legend color ribbon
g2-legend-track Continuous legend slider track
g2-legend-selection Continuous legend selection area
g2-legend-handle Continuous legend slider handle
g2-legend-handle-marker Continuous legend handle marker
g2-legend-handle-label Continuous legend label/tick value

Axis Components

className Description
g2-axis-line Axis main line
g2-axis-tick Axis tick line
g2-axis-tick-item Individual tick
g2-axis-label Axis tick label
g2-axis-label-item Individual label
g2-axis-title Axis title
g2-axis-grid Axis grid lines

Why don’t click events work on container elements?

Container elements like g2-legend-item and g2-axis are typically the outermost elements of components with transparent backgrounds and no clickable rendered area. Actual click events are triggered by their child elements and then propagate to the container through event bubbling.

Legend Component Examples:

  • ✅ g2-legend-marker:click - Click on marker icon
  • ✅ g2-legend-label:click - Click on label text
  • ❌ g2-legend-item:click - Container itself has no clickable area

Axis Component Examples:

  • ✅ g2-axis-label:click - Click on axis label
  • ✅ g2-axis-title:click - Click on axis title
  • ✅ g2-axis-line:click - Click on axis line
  • ❌ g2-axis:click - Container itself has no clickable area

How to get clicked legend item data?

Child elements (marker/label) don’t directly store complete data. Use the following approaches:

  1. Via parent container (recommended): Navigate up to the item container, get complete data via item.__data__.index + legend.attributes.data
  2. From attributes: Label’s text property, marker’s fill property contain partial information
  3. Using DOM listeners: Bind events directly on the item container, get data via item.__data__

Example: Get corresponding label when clicking marker

chart.on('g2-legend-marker:click', (e) =>  {
  const item = e.target.parentNode.parentNode;
  if (item && item.__data__) {
    // Find the actual legend component
    let legend = item.parentNode;
    while (legend && !legend.className.includes('legend-category')) {
      legend = legend.parentNode;
      if (!legend) return;
    }

    if (legend && legend.attributes && legend.attributes.data) {
      const { data } = legend.attributes;
      const { index } = item.__data__;
      const itemData = data[index];
      console.log('Clicked marker, corresponding label is:', itemData.label);
      console.log('Complete data:', itemData); // {id, label, color}
    }
  }
});

Typical Use Cases

See Interaction - Event Examples

© Copyright 2026 Ant Group Co., Ltd..备案号:京ICP备15032932号-38
Site search
Documentation and examplesType to start searching

Search documentation, APIs, and examples

↑↓Select↵OpenEscClose