# How to Combine Multiple Chart Series Types in a Single ECharts Instance

> Learn to combine multiple chart series types in ECharts using a single setOption call. Discover how to integrate line, bar, and other chart types for dynamic data visualization.

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

---

**You combine multiple chart series types in ECharts by declaring different `type` values (such as `"line"` and `"bar"`) in the `series` array of a single `setOption()` call, which leverages the global ExtensionRegister to instantiate the appropriate SeriesModel and SeriesView for each entry.**

Apache ECharts treats every visual element—whether a line, bar, scatter, or pie—as an independent **series** that can coexist within one chart instance. Because each series type registers its **SeriesModel** (data logic) and **SeriesView** (rendering logic) with the core **ExtensionRegister** during initialization, you can seamlessly mix types by supplying them in the same configuration object.

## How ECharts Registers Series Types

Before rendering, ECharts executes an internal registration pipeline that makes multi-type charts possible. This pipeline uses `install` functions found in chart-specific modules to register components with the global `registers` object.

### The ExtensionRegister Pattern

Each built-in chart type resides in its own directory under `src/chart/`. Within these directories, an [`install.ts`](https://github.com/apache/echarts/blob/main/install.ts) file handles registration:

- **Line series** – [`src/chart/line/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/line/install.ts) calls `registers.registerSeriesModel(LineSeries)` and `registers.registerChartView(LineView)`
- **Bar series** – [`src/chart/bar/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/bar/install.ts) calls `registers.registerSeriesModel(BarSeries)` and `registers.registerChartView(BarView)`

These `install` functions are aggregated and re-exported from [`src/export/charts.ts`](https://github.com/apache/echarts/blob/main/src/export/charts.ts), which ensures that when you import the ECharts bundle, every series type becomes available globally.

### Initialization and Model Instantiation

When you call `echarts.init()` (defined in [`src/echarts.ts`](https://github.com/apache/echarts/blob/main/src/echarts.ts)), the instance receives all registered renderers and models. Upon calling `setOption({ series: [...] })`, the library iterates the `series` array and performs three critical steps:

1. Reads the `type` field (e.g., `"line"` or `"bar"`) from each series object.
2. Looks up the corresponding **SeriesModel** class that was previously registered via `registers.registerSeriesModel`.
3. Creates a model instance, attaches the data, and links it to the appropriate **SeriesView** for rendering.

Because this lookup is global and type-keyed, you can declare any combination of series in one option object without manually loading separate modules.

## Combining Line and Bar Series with Dual Axes

The most common use case overlays a line series on a bar series while using separate Y-axes for different scales. In this configuration, both series share the same **Cartesian** coordinate system but bind to different axes via `yAxisIndex`.

```javascript
import * as echarts from 'echarts';

const chart = echarts.init(document.getElementById('main'));

chart.setOption({
  tooltip: { trigger: 'axis' },
  legend: { data: ['Temperature', 'Precipitation'] },
  xAxis: { type: 'category', data: ['Jan', 'Feb', 'Mar', 'Apr'] },
  yAxis: [
    { type: 'value', name: 'Temperature (°C)' },
    { type: 'value', name: 'Precipitation (mm)', position: 'right' }
  ],
  series: [
    {
      name: 'Temperature',
      type: 'line',
      data: [5, 7, 9, 13]
    },
    {
      name: 'Precipitation',
      type: 'bar',
      yAxisIndex: 1,  // Binds to the second yAxis
      data: [30, 45, 28, 60]
    }
  ]
});

```

Behind the scenes, ECharts invokes `registers.registerSeriesModel(LineSeries)` and `registers.registerSeriesModel(BarSeries)` (as defined in their respective [`install.ts`](https://github.com/apache/echarts/blob/main/install.ts) files) to handle the layout and rendering independently while synchronizing the shared X-axis categories.

## Mixing Cartesian and Polar Coordinate Systems

You can combine series that use different coordinate systems—such as **line** and **scatter** (Cartesian) alongside **pie** (polar)—in a single instance. The pie series internally manages its own polar coordinate system and does not interfere with the Cartesian grid.

```javascript
chart.setOption({
  legend: { data: ['Growth', 'Revenue', 'Market Share'] },
  tooltip: { trigger: 'item' },
  
  // Cartesian grid for line and scatter
  grid: { left: '10%', right: '55%', top: '10%', bottom: '10%' },
  xAxis: { type: 'category', data: ['Q1', 'Q2', 'Q3', 'Q4'] },
  yAxis: { type: 'value' },
  
  series: [
    {
      name: 'Growth',
      type: 'line',
      data: [12, 18, 24, 30]
    },
    {
      name: 'Revenue',
      type: 'scatter',
      symbolSize: 12,
      data: [20, 25, 28, 35]
    },
    {
      name: 'Market Share',
      type: 'pie',
      radius: '30%',
      center: ['80%', '50%'],  // Positions pie on the right
      data: [
        { value: 40, name: 'Product A' },
        { value: 35, name: 'Product B' },
        { value: 25, name: 'Product C' }
      ]
    }
  ]
});

```

The line and scatter series utilize `layoutPoints` routines registered in [`src/chart/line/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/line/install.ts) and [`src/chart/scatter/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/scatter/install.ts), while the pie series uses its own layout logic from [`src/chart/pie/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/pie/install.ts). The core dispatcher manages these disparate pipelines concurrently.

## Programmatic Registration for Custom Series

If you need to load a custom series type alongside built-ins, you can manually execute the `install` functions against the global registers before initializing the chart.

```javascript
import * as echarts from 'echarts';
import { install as LineChart } from 'echarts/src/chart/line/install';
import { install as CustomChart } from 'echarts/src/chart/custom/install';

const registers = echarts.getRegister();  // Internal API access
LineChart(registers);
CustomChart(registers);  // Register custom series

const chart = echarts.init(document.getElementById('custom'));
chart.setOption({
  series: [
    { type: 'line', data: [1, 2, 3] },
    { type: 'custom', renderItem: (params, api) => ({ /* ... */ }) }
  ]
});

```

This mirrors the internal flow found in [`src/export/charts.ts`](https://github.com/apache/echarts/blob/main/src/export/charts.ts), where built-in charts are registered en masse.

## Summary

- **SeriesModel** and **SeriesView** pairs are registered globally via `install` functions in files like [`src/chart/line/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/line/install.ts) and [`src/chart/bar/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/bar/install.ts).
- The `type` field in each series object triggers a lookup against the **ExtensionRegister**, allowing any combination of series in one `setOption` call.
- Cartesian series (line, bar, scatter) share **grid** and **axis** components, while polar series (pie) operate independently within the same canvas.
- You can manually invoke `install` functions from [`src/export/charts.ts`](https://github.com/apache/echarts/blob/main/src/export/charts.ts) or individual chart directories to register custom types programmatically.

## Frequently Asked Questions

### Can I combine more than two series types in one chart?

Yes. The ExtensionRegister architecture supports an unlimited number of series types within a single instance. Simply add additional objects to the `series` array with distinct `type` values (e.g., `"line"`, `"bar"`, `"scatter"`, `"pie"`), and ECharts will instantiate the appropriate model and view for each entry according to the registrations found in [`src/export/charts.ts`](https://github.com/apache/echarts/blob/main/src/export/charts.ts).

### Do mixed series types share the same coordinate system?

It depends on the series type. Line, bar, and scatter series default to the **Cartesian** coordinate system and share `grid` and `axis` components. Pie, radar, and gauge series use independent coordinate systems (polar or custom layouts) that do not conflict with Cartesian grids, allowing you to overlay them as separate visual layers.

### How do I bind different series to different Y-axes?

Use the `yAxisIndex` property in the series configuration. After defining multiple axes in the `yAxis` array (index 0, 1, etc.), set `yAxisIndex: 1` on the series that should use the second axis. The SeriesModel reads this index during initialization ([`src/echarts.ts`](https://github.com/apache/echarts/blob/main/src/echarts.ts)) to calculate positioning and scaling independently from other series.

### Is it possible to use custom series with built-in types?

Yes. Import the `install` function from your custom series module (following the pattern in [`src/chart/custom/install.ts`](https://github.com/apache/echarts/blob/main/src/chart/custom/install.ts)) and execute it against the global registers before calling `echarts.init`. This registers your custom **SeriesView** and **SeriesModel** alongside the built-ins exported from [`src/export/charts.ts`](https://github.com/apache/echarts/blob/main/src/export/charts.ts), allowing you to declare them in the same `series` array using your custom `type` identifier.