ECharts 快速入门
ECharts 简介
ECharts 是使用 JavaScript 实现的开源可视化库,可以流畅地运行在 PC 和移动设备上,兼容当前绝大部分浏览器。底层依赖矢量图形库 ZRender,提供直观、交互丰富、可高度个性化定制的数据可视化图表。
ECharts 特性
丰富的可视化类型
ECharts 提供常规的折线图、柱状图、散点图、饼图、K线图,用于统计的盒形图,用于地理数据可视化的地图、热力图、线图,用于关系数据可视化的关系图、treemap、旭日图,多维数据可视化的平行坐标,还有用于 BI 的漏斗图、仪表盘,并且支持图与图之间的混搭。
除了内置的图表,ECharts 还提供了自定义系列,只需要传入一个 renderItem 函数,就可以从数据映射到任何你想要的图形。
多种数据格式支持
ECharts 内置的 dataset 属性(4.0+)支持直接传入包括二维表、key-value 等多种格式的数据源,通过简单的设置 encode 属性就可以完成从数据到图形的映射。这种方式更符合可视化的直觉,省去了大部分场景下数据转换的步骤。
千万数据的前端展现
通过增量渲染技术(4.0+),配合各种细致的优化,ECharts 能够展现千万级的数据量,并且在这个数据量级依然能够进行流畅的缩放平移等交互。
移动端优化
ECharts 针对移动端交互做了细致的优化,例如移动端小屏上适于用手指在坐标系中进行缩放、平移。细粒度的模块化和打包机制可以让 ECharts 在移动端也拥有很小的体积。
多渲染方案
ECharts 支持以 Canvas、SVG(4.0+)、VML 的形式渲染图表。VML 可以兼容低版本 IE,SVG 使得移动端不再为内存担忧,Canvas 可以轻松应对大数据量和特效的展现。
深度的交互式数据探索
ECharts 提供图例、视觉映射、数据区域缩放、tooltip、数据刷选等开箱即用的交互组件,可以对数据进行多维度数据筛取、视图缩放、展示细节等交互操作。
安装方式
Apache ECharts 提供了多种安装方式,你可以根据项目的实际情况选择以下任意一种方式安装:
npm 安装(推荐)
npm install echarts全局引入
import * as echarts from 'echarts'
var myChart = echarts.init(document.getElementById('main'))
myChart.setOption({
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
})按需引入
import * as echarts from 'echarts/core'
import { BarChart } from 'echarts/charts'
import {
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent
} from 'echarts/components'
import { LabelLayout, UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
BarChart,
LabelLayout,
UniversalTransition,
CanvasRenderer
])
var myChart = echarts.init(document.getElementById('main'))
myChart.setOption({
// ...
})注意:按需引入时不再提供任何渲染器,需要选择引入
CanvasRenderer或者SVGRenderer。
TypeScript 中按需引入
import * as echarts from 'echarts/core'
import { BarChart, LineChart } from 'echarts/charts'
import {
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent
} from 'echarts/components'
import { LabelLayout, UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import type {
BarSeriesOption,
LineSeriesOption
} from 'echarts/charts'
import type {
TitleComponentOption,
TooltipComponentOption,
GridComponentOption,
DatasetComponentOption
} from 'echarts/components'
import type { ComposeOption } from 'echarts/core'
type ECOption = ComposeOption<
| BarSeriesOption
| LineSeriesOption
| TitleComponentOption
| TooltipComponentOption
| GridComponentOption
| DatasetComponentOption
>
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
BarChart,
LineChart,
LabelLayout,
UniversalTransition,
CanvasRenderer
])
const option: ECOption = {
// ...
}CDN 获取
可以从以下免费 CDN 中获取和引用 ECharts:
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>从 GitHub 获取
apache/echarts 项目的 release 页面可以找到各个版本的链接。点击下载页面下方 Assets 中的 Source code,解压后 dist 目录下的 echarts.js 即为包含完整 ECharts 功能的文件。
在线定制
如果只想引入部分模块以减少包体积,可以使用 ECharts 在线定制 功能。
初始化
在 HTML 中定义容器
通常需要在 HTML 中先定义一个 <div> 节点,并且通过 CSS 使得该节点具有宽度和高度。
<div id="main" style="width: 600px; height: 400px;"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'))
</script>注意:使用这种方法在调用
echarts.init时需保证容器已经有宽度和高度。
指定图表大小
如果图表容器不存在宽度和高度,或者希望图表宽度和高度不等于容器大小,可以在初始化时指定大小:
<div id="main"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'), null, {
width: 600,
height: 400
})
</script>响应容器大小变化
监听 resize 事件
当容器大小改变时,可以监听页面的 resize 事件,然后调用 echartsInstance.resize 改变图表大小:
<style>
#main,
html,
body {
width: 100%;
}
#main {
height: 400px;
}
</style>
<div id="main"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'))
window.addEventListener('resize', function () {
myChart.resize()
})
</script>提示:可以通过浏览器的
ResizeObserverAPI 实现更细粒度的监听。
为图表设置特定大小
除了直接调用 resize() 不含参数的形式之外,还可以指定宽度和高度:
myChart.resize({
width: 800,
height: 400
})容器销毁与重建
当图表容器被销毁后重新添加时,正确的做法是:
- 在容器被销毁时调用
echartsInstance.dispose销毁实例 - 在容器重新添加后再次调用
echarts.init初始化
提示:在容器节点被销毁时,应调用
echartsInstance.dispose以销毁实例释放资源,避免内存泄漏。
入门示例
基础柱状图
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<style>
#chart {
width: 800px;
height: 400px;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
const chartDom = document.getElementById('chart')
const chart = echarts.init(chartDom)
chart.setOption({
title: {
text: '快速入门 ECharts 开发'
},
xAxis: {
data: ['食品', '数码', '服饰', '箱包']
},
yAxis: {},
series: {
type: 'bar',
data: [100, 120, 90, 150]
}
})
</script>
</body>
</html>ECharts 绘图流程
- 引入 ECharts 库
- 编写渲染容器 DOM,添加
width和height样式属性 - 获取渲染 DOM 对象
- 初始化 ECharts 对象
- 编写
option参数 - 调用
setOption完成渲染
升级方式
在官网下载页可以下载最新版的源码和编译产物。如果使用 npm 安装,升级方式为:
npm install echarts@latest框架集成
Vue 3 集成
基础使用
<template>
<div ref="chartRef" style="width: 600px; height: 400px"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
option: { type: Object, required: true }
})
const chartRef = ref(null)
let chart = null
onMounted(() => {
chart = echarts.init(chartRef.value)
chart.setOption(props.option)
// 响应式
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
chart?.dispose()
})
watch(() => props.option, (newOption) => {
chart?.setOption(newOption)
}, { deep: true })
function handleResize() {
chart?.resize()
}
</script>使用 Composable 封装
// useChart.js
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import * as echarts from 'echarts'
export function useChart(option) {
const chartRef = ref(null)
let chart = null
const initChart = () => {
if (chartRef.value) {
chart = echarts.init(chartRef.value)
chart.setOption(option.value)
}
}
const resize = () => chart?.resize()
const setOption = (opt) => chart?.setOption(opt)
onMounted(() => {
nextTick(initChart)
window.addEventListener('resize', resize)
})
onUnmounted(() => {
window.removeEventListener('resize', resize)
chart?.dispose()
})
watch(option, (newOpt) => setOption(newOpt), { deep: true })
return { chartRef, chart, resize, setOption }
}React 集成
基础使用
import { useEffect, useRef } from 'react'
import * as echarts from 'echarts'
interface ChartProps {
option: echarts.EChartsOption
style?: React.CSSProperties
}
function Chart({ option, style }: ChartProps) {
const chartRef = useRef<HTMLDivElement>(null)
const chartInstance = useRef<echarts.ECharts | null>(null)
useEffect(() => {
if (chartRef.current) {
chartInstance.current = echarts.init(chartRef.current)
chartInstance.current.setOption(option)
}
const handleResize = () => chartInstance.current?.resize()
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
chartInstance.current?.dispose()
}
}, [])
useEffect(() => {
chartInstance.current?.setOption(option)
}, [option])
return <div ref={chartRef} style={{ width: 600, height: 400, ...style }} />
}
export default Chart使用自定义 Hook
// useChart.ts
import { useEffect, useRef, useCallback } from 'react'
import * as echarts from 'echarts'
export function useChart(option: echarts.EChartsOption) {
const chartRef = useRef<HTMLDivElement>(null)
const chart = useRef<echarts.ECharts | null>(null)
const resize = useCallback(() => chart.current?.resize(), [])
const setOption = useCallback((opt: echarts.EChartsOption) => {
chart.current?.setOption(opt)
}, [])
useEffect(() => {
if (chartRef.current) {
chart.current = echarts.init(chartRef.current)
chart.current.setOption(option)
}
window.addEventListener('resize', resize)
return () => {
window.removeEventListener('resize', resize)
chart.current?.dispose()
}
}, [])
return { chartRef, resize, setOption }
}
// 使用
function MyChart() {
const { chartRef } = useChart({
xAxis: { data: ['A', 'B', 'C'] },
yAxis: {},
series: [{ type: 'bar', data: [10, 20, 30] }]
})
return <div ref={chartRef} style={{ width: 600, height: 400 }} />
}最佳实践
1. 按需引入
推荐使用按需引入减少打包体积:
// echarts.config.js
import * as echarts from 'echarts/core'
import { BarChart, LineChart, PieChart } from 'echarts/charts'
import {
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent
} from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
echarts.use([
TitleComponent,
TooltipComponent,
LegendComponent,
GridComponent,
BarChart,
LineChart,
PieChart,
CanvasRenderer
])
export default echarts2. 内存管理
避免内存泄漏,正确销毁实例:
// 组件销毁时调用
onUnmounted(() => {
chart.dispose() // 销毁实例
chart = null // 释放引用
})
// 移除事件监听
chart.off('click') // 移除特定事件3. 响应式处理
// 使用 ResizeObserver(推荐)
const observer = new ResizeObserver(() => {
chart.resize()
})
observer.observe(container)
// 销毁时
observer.disconnect()4. 性能优化
// 初始化时开启脏矩形渲染
echarts.init(dom, null, {
useDirtyRect: true,
renderer: 'canvas' // 大数据量时优先使用 canvas
})
// 大数据量时开启优化
series: [{
type: 'scatter',
large: true, // 大数据优化
largeThreshold: 2000, // 阈值
progressive: 200 // 渐进式渲染
}]5. 防抖处理
频繁更新数据时使用防抖:
import { debounce } from 'lodash'
const updateChart = debounce((data) => {
chart.setOption({ series: [{ data }] })
}, 300)