echarts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseECharts
ECharts
Use this skill to build, audit, or fix Apache ECharts charts without turning the task into an option-reference lookup. Match the project's existing setup first; only introduce wrappers or new dependencies when the project has none.
使用此技能可以构建、审计或修复Apache ECharts图表,无需反复查阅选项参考文档。首先匹配项目现有配置;仅当项目未使用任何相关依赖时,才引入包装器或新依赖。
Decision Tree
决策树
User task -> Does the project already use ECharts?
- Yes -> Find existing chart components/helpers, reuse their init, theme,
and resize patterns. Match import style (full vs echarts/core).
- No -> Pick integration by framework:
- React -> echarts-for-react wrapper, or a small hook around
init/dispose if the project avoids extra deps
- Vue 3 -> vue-echarts wrapper, or composable around init/dispose
- Vanilla / other -> echarts.init on a sized container
Next -> Bundle size a concern (app ships to users)?
- Yes -> Import from 'echarts/core' and register only the used charts,
components, and renderer (tree-shaking)
- No / internal tool / prototype -> import * as echarts from 'echarts'
Then -> Build the smallest working option, render it, then layer on
interactivity (tooltip, dataZoom, toolbox) and theming.用户任务 -> 项目是否已使用ECharts?
- 是 -> 查找现有图表组件/辅助工具,复用其初始化、主题和缩放模式。匹配导入风格(完整导入 vs echarts/core)。
- 否 -> 根据框架选择集成方式:
- React -> 使用echarts-for-react包装器,若项目避免额外依赖则基于init/dispose编写小型钩子
- Vue 3 -> 使用vue-echarts包装器,或基于init/dispose编写组合式函数
- 原生JS / 其他 -> 在已设置尺寸的容器上调用echarts.init
下一步 -> 是否关注包体积(应用需交付给用户)?
- 是 -> 从'echarts/core'导入,并仅注册使用到的图表、组件和渲染器(摇树优化)
- 否 / 内部工具 / 原型 -> 导入* as echarts from 'echarts'
然后 -> 构建最小可用配置并渲染,再逐步添加交互功能(提示框、数据区域缩放、工具栏)和主题配置。Core Workflow
核心工作流
- Inspect first: find existing ECharts usage, themes, and shared option helpers before writing a new chart.
- Size the container: the container element must have non-zero width and height before runs; a chart in a display:none or unmounted tab renders blank.
echarts.init - Own the lifecycle: one per container,
initon container size change,resize()on unmount. Wrappers handle this; hand-rolled code must.dispose() - Update via : default merge mode for incremental updates (streaming, new data);
setOptionwhen the chart type or structure changes.notMerge: true - Verify visually: render the chart and check axes, labels, and tooltip against real data before polishing.
- 先检查:在编写新图表前,查找现有ECharts用法、主题和共享配置辅助工具。
- 设置容器尺寸:在执行前,容器元素必须具备非零宽高;处于display:none状态或未挂载标签页中的图表会渲染为空白。
echarts.init - 管理生命周期:每个容器对应一次,容器尺寸变化时调用
init,卸载时调用resize()。包装器会处理这些逻辑;手动编写的代码必须实现这些步骤。dispose() - 通过更新:默认合并模式用于增量更新(流式数据、新数据);当图表类型或结构变化时,使用
setOption。notMerge: true - 视觉验证:渲染图表后,对照真实数据检查坐标轴、标签和提示框,再进行优化。
Setup
安装
bash
npm install echarts # core library (always)
npm install echarts-for-react # React wrapper (optional)
npm install vue-echarts # Vue 3 wrapper (optional)Tree-shakeable imports for production bundles:
ts
import * as echarts from 'echarts/core';
import { LineChart, BarChart } from 'echarts/charts';
import { GridComponent, TooltipComponent, DataZoomComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([LineChart, BarChart, GridComponent, TooltipComponent, DataZoomComponent, CanvasRenderer]);A missing registration fails at runtime with a console error naming the missing chart/component — register it, do not switch to full import to silence the error. It is a , not a thrown exception, so unit tests pass silently over it; catch it by asserting on the console or the rendered output.
console.errorWith multiple chart components in one codebase, prefer a shared registration module (one call imported everywhere) over per-component lists — per-component lists drift out of sync and hide missing registrations until a component renders alone. Deliberate feature-specific registration in code-split routes is a valid exception for lazy-loaded dashboards.
echarts.use([...])useType imports: is erased at compile time and does not affect the bundle — only value imports from the root package pull everything in. Some types (, ) are exported only from the root, so mixing from with values from is normal; prefer from for option types:
import type { ... } from 'echarts'XAXisComponentOptionDefaultLabelFormatterCallbackParamsimport type'echarts''echarts/core'ComposeOption'echarts/core'ts
import type { ComposeOption } from 'echarts/core';
import type { LineSeriesOption } from 'echarts/charts';
import type { GridComponentOption, TooltipComponentOption } from 'echarts/components';
type ChartOption = ComposeOption<LineSeriesOption | GridComponentOption | TooltipComponentOption>;bash
npm install echarts # 核心库(必装)
npm install echarts-for-react # React包装器(可选)
npm install vue-echarts # Vue 3包装器(可选)生产包的摇树优化导入方式:
ts
import * as echarts from 'echarts/core';
import { LineChart, BarChart } from 'echarts/charts';
import { GridComponent, TooltipComponent, DataZoomComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
echarts.use([LineChart, BarChart, GridComponent, TooltipComponent, DataZoomComponent, CanvasRenderer]);缺少注册会在运行时触发控制台错误,提示缺失的图表/组件——注册该组件即可,不要通过完整导入来掩盖错误。这是而非抛出异常,因此单元测试会静默通过;可通过断言控制台输出或渲染结果来捕获该问题。
console.error若代码库中有多个图表组件,优先使用共享注册模块(一处调用,各处导入),而非每个组件单独维护列表——单独列表会逐渐不一致,且只有当组件单独渲染时才会暴露缺失的注册。对于懒加载仪表盘,在代码拆分路由中刻意进行特定功能的注册是合理的例外情况。
echarts.use([...])use类型导入:会在编译时被移除,不影响包体积——只有从根包导入值才会引入全部内容。部分类型(如、)仅从根包导出,因此混合使用(来自)和值导入(来自)是正常的;优先使用中的作为配置类型:
import type { ... } from 'echarts'XAXisComponentOptionDefaultLabelFormatterCallbackParamsimport type'echarts''echarts/core''echarts/core'ComposeOptionts
import type { ComposeOption } from 'echarts/core';
import type { LineSeriesOption } from 'echarts/charts';
import type { GridComponentOption, TooltipComponentOption } from 'echarts/components';
type ChartOption = ComposeOption<LineSeriesOption | GridComponentOption | TooltipComponentOption>;Lifecycle Rules
生命周期规则
- Vanilla: keep the chart instance; call from a
chart.resize()on the container; callResizeObserverbefore removing the container.chart.dispose() - React (echarts-for-react): pass as a prop; use
optionprop when replacing structure; get the instance vianotMergeonly for imperative needs (streamingref.getEchartsInstance(),setOption).dispatchAction - React (hand-rolled hook): in an effect,
initin its cleanup; keepdisposeupdates in a separate effect so the chart is not re-created on every render.option - Vue (vue-echarts): use binding with
:option; access the instance via template ref forautoresize. PassdispatchActionfor structural option changes (chart type, series count, removing axes/series) — merge mode keeps stale series. Switch themes via the:update-options="{ notMerge: true }"prop orthemeinjection, notTHEME_KEY(on older ECharts/vue-echarts versions, remount/re-init instead). Use theupdate-optionsprop to link charts (equivalent togroup).echarts.connect - Never call twice on the same DOM node; reuse the instance or dispose first (
echarts.initto check).echarts.getInstanceByDom
- 原生JS:保留图表实例;通过容器上的调用
ResizeObserver;移除容器前调用chart.resize()。chart.dispose() - React(echarts-for-react):将作为属性传递;替换结构时使用
option属性;仅在需要命令式操作(流式notMerge、setOption)时,通过dispatchAction获取实例。ref.getEchartsInstance() - React(手动编写钩子):在副作用中执行,在清理函数中执行
init;将dispose更新放在单独的副作用中,避免图表在每次渲染时重新创建。option - Vue(vue-echarts):使用绑定并开启
:option;通过模板引用访问实例以执行autoresize。当配置结构变化(图表类型、系列数量、移除坐标轴/系列)时,传递dispatchAction——合并模式会保留过时的系列数据。通过:update-options="{ notMerge: true }"属性或theme注入切换主题,而非使用THEME_KEY(在旧版ECharts/vue-echarts中,需重新挂载/初始化)。使用update-options属性关联图表(等同于group)。echarts.connect - 切勿在同一DOM节点上多次调用;复用实例或先执行
echarts.init(可通过dispose检查)。echarts.getInstanceByDom
Data and Options
数据与配置
- Prefer the component (
dataset+source) when multiple series or charts share one table of data; use per-seriesencodefor simple single-series charts.data - Time series: use with
xAxis: { type: 'time' }pairs instead of pre-formatting date strings into a category axis.[timestamp, value] - Large categorical axes: set /
axisLabel.intervaldeliberately instead of accepting overlap.rotate - Tooltips: for line/bar time series,
trigger: 'axis'for pie/scatter/map.trigger: 'item' - Use or
valueFormatterfor units; keep number formatting in one shared helper when the dashboard has many charts.tooltip.formatter - HTML tooltip output is injected as HTML: escape untrusted data (series names, user-generated labels) with a shared escape helper, or use
formatterto opt out of HTML entirely.tooltip.renderMode: 'richText'
- 当多个系列或图表共享一份数据表时,优先使用组件(
dataset+source);简单单系列图表使用每个系列的encode。data - 时间序列:使用搭配
xAxis: { type: 'time' }数组,而非将日期字符串预格式化为分类坐标轴。[时间戳, 值] - 大型分类坐标轴:刻意设置/
axisLabel.interval,避免标签重叠。rotate - 提示框:折线/柱状时间序列使用,饼图/散点图/地图使用
trigger: 'axis'。trigger: 'item' - 使用或
valueFormatter处理单位;当仪表盘包含多个图表时,将数字格式化逻辑放在共享辅助工具中。tooltip.formatter - HTML提示框的输出会以HTML形式注入:使用共享转义工具对不可信数据(系列名称、用户生成的标签)进行转义,或使用
formatter完全禁用HTML。tooltip.renderMode: 'richText'
Performance
性能优化
- Canvas (default renderer) is fine up to ~100K points; use SVG renderer only for small charts needing crisp export or DOM-level styling.
- For large line/scatter series: enable and
large: trueon the series; turn offsampling: 'lttb'for initial render of big datasets.animation - Millions of points: use (WebGL) — a separate dependency; add it only when actually needed.
echarts-gl - Streaming: call on the existing instance (merge mode); do not re-init or pass
setOption({ series: [{ data }] })per tick.notMerge - Many charts on one page: share a single /resize handler and use
ResizeObserverfor linked tooltips/dataZoom instead of duplicating handlers.echarts.connectis also a UX feature for dashboards:connect(or the vue-echartschart.group = 'name'; echarts.connect('name')prop) syncs tooltips and dataZoom across related charts. Only link charts with compatible axis semantics (same x-axis type and domain); a chart with a different axis belongs in its own group or unlinked.group
- Canvas(默认渲染器)在处理约10万数据点时表现良好;仅在需要清晰导出或DOM级样式的小型图表中使用SVG渲染器。
- 大型折线/散点系列:在系列上启用和
large: true;大数据集初始渲染时关闭sampling: 'lttb'。animation - 百万级数据点:使用(WebGL)——这是一个独立依赖;仅在实际需要时添加。
echarts-gl - 流式数据:在现有实例上调用(合并模式);不要每次更新都重新初始化或传递
setOption({ series: [{ data }] })。notMerge - 单页多图表:共享单个/缩放处理函数,并使用
ResizeObserver实现关联提示框/数据区域缩放,避免重复处理函数。echarts.connect也是仪表盘的UX特性:connect(或vue-echarts的chart.group = 'name'; echarts.connect('name')属性)可同步关联图表的提示框和数据区域缩放。仅关联具有兼容坐标轴语义(相同x轴类型和范围)的图表;坐标轴不同的图表应单独分组或不关联。group
Theming
主题配置
- Register a theme once () and pass the name to every
echarts.registerTheme('name', themeObject); do not copy color arrays into each chart's option.init - Dark mode: prefer plus a registered dark theme, or
init(el, null, ...)in the option. Switch themes at runtime withdarkMode: true(ECharts 6) or the vue-echartschart.setTheme(...)prop; on ECharts 5 themes are fixed at init time — re-init (dispose + init) there.theme - Keep chart-independent styling (font family, palette) in the theme; keep data-dependent styling (visualMap ranges, markLines) in the option.
- 注册一次主题(),并在每次
echarts.registerTheme('name', themeObject)时传递主题名称;不要将颜色数组复制到每个图表的配置中。init - 暗黑模式:优先使用搭配已注册的暗黑主题,或在配置中设置
init(el, null, ...)。在运行时切换主题可使用darkMode: true(ECharts 6)或vue-echarts的chart.setTheme(...)属性;在ECharts 5中主题在初始化时固定——需重新初始化(dispose + init)。theme - 将与图表无关的样式(字体族、调色板)放在主题中;将与数据相关的样式(视觉映射范围、标记线)放在配置中。
SSR and Export
SSR与导出
- Server-side rendering (reports, emails, OG images): then
echarts.init(null, null, { renderer: 'svg', ssr: true, width, height })— Node only, no DOM needed.renderToSVGString() - If option builders are shared between the browser and a Node SVG renderer, keep both registration points covering the same set — a narrower server-side list silently renders without the missing components.
echarts.use([...]) - Client image export: enable , or call
toolbox.feature.saveAsImageprogrammatically.chart.getDataURL({ pixelRatio: 2 })
- 服务端渲染(报表、邮件、OG图片):,然后调用
echarts.init(null, null, { renderer: 'svg', ssr: true, width, height })——仅支持Node环境,无需DOM。renderToSVGString() - 若配置构建器在浏览器和Node SVG渲染器之间共享,确保两处注册的组件集一致——服务端注册范围过窄会静默渲染缺失的组件。
echarts.use([...]) - 客户端图片导出:启用,或通过编程方式调用
toolbox.feature.saveAsImage。chart.getDataURL({ pixelRatio: 2 })
ECharts 6 Migration Notes
ECharts 6迁移注意事项
- is deprecated. The semantics-preserving migration is
grid.containLabel→containLabel: true; set{ outerBoundsMode: 'same', outerBoundsContain: 'axisLabel' }only when you need a custom constraint rect (it is a separate part of the new layout API). The legacy behavior still works only ifgrid.outerBounds(fromLegacyGridContainLabel) is registered — treat remaining'echarts/features'usages as tech debt when auditing.containLabel: true - The default theme changed in v6 (palette and component layout). To keep the v5 look during migration: and pass
import 'echarts/theme/v5'as the theme to'v5'.init - Axis label overflow prevention and axis-name overlap prevention are on by default in v6, which can shift layouts slightly; disable with and
grid.outerBoundsMode: 'none'when pixel-parity with v5 matters.xAxis/yAxis.nameMoveOverlap: false - Check the installed major version () before recommending options; deprecations surface as console warnings, not errors.
node_modules/echarts/package.json
- 已废弃。语义保留的迁移方式是
grid.containLabel→containLabel: true;仅当需要自定义约束矩形时才设置{ outerBoundsMode: 'same', outerBoundsContain: 'axisLabel' }(这是新布局API的独立部分)。只有注册了grid.outerBounds(来自LegacyGridContainLabel),旧行为才会生效——审计时将剩余的'echarts/features'用法视为技术债务。containLabel: true - v6默认主题已更改(调色板和组件布局)。若迁移期间需保留v5外观:并在
import 'echarts/theme/v5'时传递init作为主题。'v5' - v6默认启用坐标轴标签溢出预防和轴名称重叠预防,这可能导致布局略有偏移;当需要与v5像素级一致时,可通过和
grid.outerBoundsMode: 'none'禁用。xAxis/yAxis.nameMoveOverlap: false - 在推荐配置前,检查已安装的主版本();废弃API会以控制台警告而非错误形式出现。
node_modules/echarts/package.json
Auditing Existing Usage
审计现有用法
When reviewing (not building) a codebase's ECharts usage, check in order:
- Registrations: one shared module vs per-component lists that drift; missing or duplicated registrations; with SSR, verify the client and server
use([...])lists cover the same components.use([...]) - Lifecycle: every has a matching
init; resize observed on the container, not the window.dispose - Update semantics: /
notMergeused where chart type, series count, or axes/series are removed.update-options - Imports: value imports from root in tree-shaken builds;
'echarts'is fine.import type - Deprecated API: and other version-migration debt (see migration notes above).
containLabel - Duplication: repeated option/formatter logic that belongs in a shared helper or registered theme.
审查(而非构建)代码库中的ECharts用法时,按以下顺序检查:
- 注册:是否使用单个共享模块,而非逐渐不一致的组件单独列表;是否存在缺失或重复注册;若使用SSR,验证客户端和服务端
use([...])列表包含相同组件。use([...]) - 生命周期:每个是否对应
init;是否监听容器而非窗口的缩放事件。dispose - 更新语义:在图表类型、系列数量或坐标轴/系列被移除时,是否使用/
notMerge。update-options - 导入:摇树优化构建中是否从根导入值;
'echarts'是允许的。import type - 废弃API:及其他版本迁移债务(见上述迁移注意事项)。
containLabel - 重复代码:重复的配置/格式化逻辑是否应放在共享辅助工具或已注册的主题中。
Common Failure Modes
常见故障模式
- Blank chart, no error: container had zero size at init (hidden tab, flex parent without height, init before mount). Fix sizing/timing, then call .
resize() - Chart does not update: a new option object with merge mode silently keeps stale series/axes — use when removing series or changing chart type.
notMerge: true - Legend/dataZoom selection lost after update: resets interactive state; capture
notMerge: true(and dataZoom range) before the update and pass it back in the new option.chart.getOption().legend[0].selected - "Component xxx not exists" / missing chart: tree-shaken build without the registration; add it to .
echarts.use([...]) - Memory growth in SPA: instances not disposed on route change; verify runs in unmount cleanup.
dispose() - Chart wrong size after sidebar/panel toggle: window event never fired; observe the container (ResizeObserver /
resize), not the window.autoresize - Tooltip clipped: set or
tooltip.confine: true-styleappendToBodywhen the chart sits in an overflow-hidden container.tooltip.appendTo - Sluggish with big data: animation on + no sampling; set ,
animation: false,sampling: 'lttb'before reaching for WebGL.large: true
- 空白图表,无错误:初始化时容器尺寸为零(隐藏标签页、无高度的flex父元素、挂载前初始化)。修复尺寸/时机后调用。
resize() - 图表不更新:合并模式下的新配置对象会静默保留过时的系列/坐标轴——移除系列或更改图表类型时使用。
notMerge: true - 更新后图例/数据区域缩放选择丢失:会重置交互状态;更新前捕获
notMerge: true(以及数据区域缩放范围),并在新配置中传递回去。chart.getOption().legend[0].selected - "Component xxx not exists" / 图表缺失:摇树优化构建未注册该组件;将其添加到中。
echarts.use([...]) - SPA中内存增长:路由切换时未销毁实例;验证在卸载清理时执行。
dispose() - 侧边栏/面板切换后图表尺寸错误:未触发窗口事件;监听容器(ResizeObserver /
resize)而非窗口。autoresize - 提示框被裁剪:当图表处于overflow-hidden容器中时,设置或类似
tooltip.confine: true的appendToBody。tooltip.appendTo - 大数据下性能缓慢:启用了动画且未使用采样;在考虑WebGL前,先设置、
animation: false、sampling: 'lttb'。large: true
Reference Examples
参考示例
- - Vanilla JS time-series line chart with resize handling
examples/vanilla_line.html - - React component with tree-shaken imports and echarts-for-react
examples/react_chart.tsx - - Vue 3 component using vue-echarts with autoresize
examples/vue_chart.vue
- - 原生JS时间序列折线图,带缩放处理
examples/vanilla_line.html - - React组件,使用摇树优化导入和echarts-for-react
examples/react_chart.tsx - - Vue 3组件,使用vue-echarts并启用自动缩放
examples/vue_chart.vue