# ECharts Custom Series Rendering: Complete Guide to Building Specialized Visualizations with renderItem

> Master ECharts custom series rendering to build unique visualizations. Learn to use renderItem for bespoke graphics leveraging ECharts' coordinate systems and animations.

- Repository: [The Apache Software Foundation/echarts](https://github.com/apache/echarts)
- Tags: how-to-guide
- Published: 2026-03-04

---

**ECharts custom series rendering enables you to create bespoke visualizations by implementing a `renderItem` function that returns ZRender graphic element descriptors for each data point, while leveraging the library's built-in coordinate systems and animation infrastructure.**

The `custom` series type in Apache ECharts provides a powerful escape hatch for building specialized charts that extend beyond standard bar, line, and scatter types. By implementing a `renderItem` function and utilizing the coordinate system API exposed through [`src/chart/custom/CustomView.ts`](https://github.com/apache/echarts/blob/main/src/chart/custom/CustomView.ts), you can render arbitrary graphics—from custom bars and heatmaps to particle systems—while retaining ECharts' data binding, visualMap integration, and stateful interactions.

## Architecture of ECharts Custom Series Rendering

### Series Registration and Model Definition

In [`src/chart/custom/CustomSeries.ts`](https://github.com/apache/echarts/blob/main/src/chart/custom/CustomSeries.ts), the `CustomSeriesModel` registers the series type and defines default options such as `coordinateSystem: 'cartesian2d'`. This model holds the data and configuration that the view layer consumes during the rendering cycle. The series option object follows the `CustomSeriesOption` type signature, requiring either a function or registered string name for the `renderItem` property.

### The renderItem Function Resolution

The `CustomChartView` class in [`src/chart/custom/CustomView.ts`](https://github.com/apache/echarts/blob/main/src/chart/custom/CustomView.ts) orchestrates the rendering pipeline through its `makeRenderItem` method. According to the source code, this method resolves the `renderItem` option by checking if it is a string reference to a function registered via `echarts.registerCustomSeries` (stored in [`src/chart/custom/customSeriesRegister.ts`](https://github.com/apache/echarts/blob/main/src/chart/custom/customSeriesRegister.ts)), or a direct function implementation. This resolution happens before the data iteration begins, allowing the view to optimize the render loop.

### Coordinate System Preparation and API Construction

Before invoking your render function for each data item, ECharts prepares coordinate-specific helpers through `prepareCustoms` (implemented in files like [`src/coord/cartesian/prepareCustom.ts`](https://github.com/apache/echarts/blob/main/src/coord/cartesian/prepareCustom.ts)). These helpers provide geometric transformations that map data values to canvas coordinates. The view constructs a `userAPI` object exposing methods like `api.coord()`, `api.size()`, `api.value()`, `api.style()`, `api.visual()`, `api.barLayout()`, and `api.font()`, combining the core `ExtensionAPI` with coordinate-system-specific utilities.

### Element Creation and State Management

The view iterates over data indices using `data.diff(...).update(...)` and invokes `renderItem` with per-item parameters containing the data index, raw values, and encoded dimensions. The function returns a `CustomRootElementOption` tree describing ZRender graphic elements. The `createOrUpdateItem` method in [`CustomView.ts`](https://github.com/apache/echarts/blob/main/CustomView.ts) converts these descriptors into actual ZRender shapes (paths, images, text, groups) via factories in [`src/util/graphic.ts`](https://github.com/apache/echarts/blob/main/src/util/graphic.ts). The pipeline handles state transitions (normal, emphasis, blur, select) through `updateElNormal` and `updateElOnState`, maintaining backward compatibility with EC4 style syntax via `convertToEC4StyleForCustomSerise` in [`src/util/styleCompat.ts`](https://github.com/apache/echarts/blob/main/src/util/styleCompat.ts).

## Implementing Custom Series in ECharts

### Basic renderItem Example: Drawing Custom Circles

The following example demonstrates a minimal `renderItem` implementation that draws circles with radii proportional to data values:

```javascript
option = {
  xAxis: { type: 'category' },
  yAxis: { type: 'value' },
  series: [{
    type: 'custom',
    renderItem: function (params, api) {
      const x = api.coord([api.value(0), 0])[0];
      const y = api.coord([0, api.value(1)])[1];
      const size = api.value(1) * 2;   // radius proportional to the Y value
      return {
        type: 'circle',
        shape: { cx: x, cy: y, r: size },
        style: api.style({ fill: 'steelblue' })
      };
    },
    data: [
      ['Mon', 120],
      ['Tue', 200],
      ['Wed', 150],
      ['Thu', 80],
      ['Fri', 70]
    ]
  }]
};

```

**Key implementation details:**
- `api.coord` converts data tuples to canvas coordinates using the current coordinate system.
- `api.value(dim)` retrieves the raw value of the specified dimension for the current data item.
- `api.style` builds a style object that automatically merges visualMap settings, itemStyle configurations, and theme defaults.

### Registering Reusable renderItem Functions

For complex rendering logic or multi-chart reuse, register the function via `echarts.registerCustomSeries` and reference it by name:

```javascript
// Register a named renderItem function
echarts.registerCustomSeries('myBar', function (params, api) {
  const x = api.coord([api.value(0), 0])[0];
  const y0 = api.coord([api.value(0), 0])[1];
  const y1 = api.coord([api.value(0), api.value(1)])[1];
  const width = api.size([1, 0])[0] * 0.6;  // bar width from coordinate system
  
  return {
    type: 'rect',
    shape: {
      x: x - width / 2,
      y: y1,
      width: width,
      height: Math.max(y0 - y1, 0)
    },
    style: api.style({ fill: '#5470C6' })
  };
});

option = {
  series: [{
    type: 'custom',
    renderItem: 'myBar',   // string reference to registered function
    coordinateSystem: 'cartesian2d',
    data: [
      { value: ['A', 120] }, 
      { value: ['B', 200] }, 
      { value: ['C', 150] }
    ]
  }]
};

```

**Why register?** The registration map in [`customSeriesRegister.ts`](https://github.com/apache/echarts/blob/main/customSeriesRegister.ts) stores render functions keyed by string identifiers, enabling code reuse across multiple chart instances and keeping option objects lightweight and serializable.

### Advanced API Usage: Coordinate Systems and Visual Mappings

Leverage the full `CustomSeriesRenderItemAPI` for complex layouts including bar positioning and dynamic coloring:

```javascript
option = {
  series: [{
    type: 'custom',
    renderItem: function (params, api) {
      const x = api.coord([api.value(0), 0])[0];
      const y = api.coord([0, api.value(1)])[1];
      const [barX, barWidth] = api.barLayout({ gap: 2, maxWidth: 30 });
      
      return {
        type: 'group',
        children: [
          {
            type: 'rect',
            shape: {
              x: barX,
              y: y,
              width: barWidth,
              height: api.getHeight() - y
            },
            style: api.style({
              fill: api.visual('color')  // retrieve visualMap color
            })
          },
          {
            type: 'text',
            style: {
              text: api.value(1),
              x: x,
              y: y - 5,
              textAlign: 'center',
              fill: '#333',
              font: api.font({ fontSize: 12 })  // theme-aware font
            }
          }
        ]
      };
    },
    data: [
      { value: ['Jan', 320] }, 
      { value: ['Feb', 432] }, 
      { value: ['Mar', 501] }
    ],
    coordinateSystem: 'cartesian2d',
    clip: true  // enable coordinate system clipping
  }]
};

```

**Advanced capabilities:**
- `api.barLayout` returns computed bar positions and widths for Cartesian series, essential for waterfall or stacked bar customizations.
- `api.visual('color')` retrieves dynamically assigned colors from visualMap components.
- `api.font` generates font strings respecting the current theme's typography settings.
- The `clip: true` option creates a clipping path from the coordinate system boundaries, preventing elements from rendering outside the grid.

## Summary

- **Custom series rendering** in ECharts is implemented through the `renderItem` function in [`src/chart/custom/CustomView.ts`](https://github.com/apache/echarts/blob/main/src/chart/custom/CustomView.ts), which receives a rich API and returns ZRender element descriptors.
- **Coordinate system integration** happens via `prepareCustoms` helpers that provide `api.coord()` and `api.size()` methods for converting data values to pixel coordinates.
- **Function registration** via `echarts.registerCustomSeries` allows complex render logic to be reused across charts by referencing string names in the series option.
- **Element lifecycle management** includes automatic creation, updates, state transitions (emphasis, blur, select), and compatibility conversion for legacy ECharts 4 styles.
- **Performance optimizations** such as `clip` for boundary restriction and `incrementalRender` for large datasets are built into the `CustomChartView` rendering pipeline.

## Frequently Asked Questions

### How does the renderItem function receive coordinate data?

The `renderItem` function receives coordinate transformation capabilities through the second argument `api`, which is constructed by `CustomChartView` from the current coordinate system's `prepareCustoms` helpers. Methods like `api.coord([x, y])` convert data values to canvas coordinates, while `api.size([dx, dy])` converts data deltas to pixel distances. This abstraction allows the same render function to work across Cartesian, polar, geo, and other coordinate systems without modification.

### Can I use custom series with polar or geo coordinate systems?

Yes, the custom series architecture supports any coordinate system registered in ECharts. The `prepareCustoms` method in [`src/chart/custom/CustomView.ts`](https://github.com/apache/echarts/blob/main/src/chart/custom/CustomView.ts) dynamically selects the appropriate coordinate helper based on the series' `coordinateSystem` option (e.g., `'polar'`, `'geo'`, `'singleAxis'`). Each coordinate system implementation (such as [`src/coord/polar/prepareCustom.ts`](https://github.com/apache/echarts/blob/main/src/coord/polar/prepareCustom.ts)) provides specialized `coord` and `size` methods that handle the specific projection mathematics for that system.

### What is the performance impact of custom series rendering?

Custom series performance depends on the complexity of your `renderItem` function and the number of data items. The view implements `incrementalRender` for large datasets, allowing progressive rendering that maintains responsiveness. Additionally, ECharts' diff algorithm in the data update cycle ensures that only changed elements are modified, reused, or created, minimizing DOM or canvas operations. For optimal performance, avoid expensive computations inside `renderItem` and use the `clip` option to cull off-screen elements.

### How do I handle animations and state transitions in custom series?

State transitions are handled automatically by the `createOrUpdateItem` logic in [`CustomView.ts`](https://github.com/apache/echarts/blob/main/CustomView.ts), which processes style definitions for normal, emphasis, blur, and select states. When returning elements from `renderItem`, you can specify state-specific styles in the `style` property or use `api.style()` to inherit theme configurations. The [`customGraphicTransition.ts`](https://github.com/apache/echarts/blob/main/customGraphicTransition.ts) module manages enter, update, and leave animations. To ensure smooth transitions, maintain consistent element IDs between updates and utilize the `transition` property in your graphic element descriptors.