ECharts Custom Series Rendering: Complete Guide to Building Specialized Visualizations with renderItem
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, 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, 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 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), 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). 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 converts these descriptors into actual ZRender shapes (paths, images, text, groups) via factories in 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.
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:
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.coordconverts 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.stylebuilds 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:
// 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 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:
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.barLayoutreturns 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.fontgenerates font strings respecting the current theme's typography settings.- The
clip: trueoption 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
renderItemfunction insrc/chart/custom/CustomView.ts, which receives a rich API and returns ZRender element descriptors. - Coordinate system integration happens via
prepareCustomshelpers that provideapi.coord()andapi.size()methods for converting data values to pixel coordinates. - Function registration via
echarts.registerCustomSeriesallows 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
clipfor boundary restriction andincrementalRenderfor large datasets are built into theCustomChartViewrendering 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 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) 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, 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →