ECharts一个基于 JavaScript 的开源可视化图表库。目录效果一、介绍1、官方文档Apache ECharts2、官方示例二、准备工作1、安装依赖包2、示例版本三、使用步骤1、在单页面引入 echarts2、指定容器并设置容器宽高3、数据处理关键点1三角尖峰2一个分类一个 series四、完整示例运行方式五、可能出现的问题踩坑记录1、五个三角一样高2、tooltip 一次弹出五行没值的显示成 -3、控制台报 Cant get DOM width or height4、切页面回来图表变白窗口缩放图表不跟着变5、改了轴线的颜色轴上的文字跟着一起变浅结语欢迎关注【前端小知识营地】效果一、介绍1、官方文档Apache EChartsApache ECharts一个基于 JavaScript 的开源可视化图表库提供直观、生动、可交互、可个性化定制的数据可视化图表。2、官方示例官方示例里有一个象形柱图-山峰画的就是三角形山参数可以直接对着改。二、准备工作1、安装依赖包npm install echarts --save2、示例版本echarts: ^5.5.1,三、使用步骤1、在单页面引入 echartsimport * as echarts from echarts;注上面的代码会引入 ECharts 中所有的图表和组件如果你不想引入所有组件也可以使用 ECharts 提供的按需引入的接口来打包必需的组件。详见官方文档在项目中引入 ECharts。2、指定容器并设置容器宽高template div idpeakShapeMain/div /template script langts setup import * as echarts from echarts; initChart() { let chartDom document.getElementById(peakShapeMain); let myChart echarts.init(chartDom); let option; ...详见完整示例 }; /script style langscss scoped #peakShapeMain { width: 600px; height: 340px; } /style容器要有确定的宽高高度是 0 的时候echarts.init会直接报「Cant get DOM width or height」。3、数据处理关键点1三角尖峰series: [ { type: pictorialBar, symbol: triangle, symbolSize: [72, 100%], /* 宽 72高度跟柱体一样长 */ ...详见完整示例 }, ],pictorialBar是象形柱图跟bar一样按数值定长度区别只是把柱子的形状换成了symbol。symbol: triangle就是三角symbolSize的高度写100%表示「跟柱体一样长」也就是从 0 长到数值——写死像素值的话82 和 63 画出来会一样高。关于pictorialBar的完整参数见官方文档series-pictorialBar。2一个分类一个 series图例要按分类分开显示、点一下能单独隐藏某个分类就得一个分类给一个 series每个 series 只在自己那一格给值、其余填nullseries: CATEGORIES.map((item, index) ({ name: item.name, type: pictorialBar, symbol: triangle, symbolSize: [72, 100%], itemStyle: { color: item.color }, label: { show: true, position: top }, data: CATEGORIES.map((_, i) (i index ? item.value : null)), })),null表示这一格没有数据ECharts 不会画别顺手换成00会被当成真实数据参与计算。label.position: top是三角尖上方那个数值。还有一处顺带处理trigger: axis的 tooltip 默认会把 5 个 series 都列出来没值的显示成-。完整示例里自己写了formatter先filter掉空值再拼字符串停在哪个分类就只弹哪一行。四、完整示例template div idpeakShapeMain/div /template script langts setup namepeakShape import * as echarts from echarts import { nextTick, onBeforeUnmount, onMounted } from vue const CATEGORIES [ { name: 分类一, color: #1890ff, value: 82 }, { name: 分类二, color: #91cc75, value: 63 }, { name: 分类三, color: #fac858, value: 86 }, { name: 分类四, color: #ee6666, value: 65 }, { name: 分类五, color: #73c0de, value: 79 }, ] /** y 轴刻度间隔数据量级变了就改这里比如上万就把 20 换成 2000 */ const AXIS_INTERVAL 20 /** 顶部留白系数给最高的三角上面留一截别让尖顶贴到轴顶 */ const AXIS_HEADROOM 1.1 const MAX_VALUE Math.max(...CATEGORIES.map((item) item.value)) /** y 轴最大值最大值上浮后向上取整到刻度间隔的整数倍86 × 1.1 94.6 → 100 */ const AXIS_MAX Math.ceil((MAX_VALUE * AXIS_HEADROOM) / AXIS_INTERVAL) * AXIS_INTERVAL let myChart: echarts.ECharts | null null const handleResize () myChart?.resize() const initChart () { const chartDom document.getElementById(peakShapeMain) if (!chartDom) return myChart echarts.init(chartDom) myChart.setOption({ tooltip: { confine: true, trigger: axis, axisPointer: { type: line, lineStyle: { color: #999, type: dashed } }, backgroundColor: rgba(17, 25, 40, 0.9), borderColor: rgba(255, 255, 255, 0.1), borderWidth: 1, textStyle: { color: #FFFFFF, fontSize: 12 }, /* 5 个 series 里只有 1 个有值过滤掉空的只显示当前这一项 */ formatter: (params) params .filter((item) item.value ! null item.value ! undefined) .map((item) ▲ item.seriesName : item.value) .join(br/), }, legend: { bottom: 0, itemWidth: 10, itemHeight: 10, }, grid: { top: 30, left: 12, right: 20, bottom: 46, containLabel: true, }, xAxis: { type: category, data: CATEGORIES.map((item) item.name), axisTick: { show: false }, axisLine: { lineStyle: { color: #e0e0e0 } }, axisLabel: { color: #333333 }, }, yAxis: { type: value, max: AXIS_MAX, interval: AXIS_INTERVAL, splitLine: { lineStyle: { color: #f0f0f0 } }, axisLabel: { color: #333333 }, }, series: CATEGORIES.map((item, index) ({ name: item.name, type: pictorialBar, symbol: triangle, symbolSize: [72, 100%], itemStyle: { color: item.color }, label: { show: true, position: top }, data: CATEGORIES.map((_, i) (i index ? item.value : null)), })), }) window.addEventListener(resize, handleResize) } onMounted(async () { await nextTick() initChart() }) onBeforeUnmount(() { window.removeEventListener(resize, handleResize) myChart?.dispose() myChart null }) /script style langscss scoped #peakShapeMain { width: 600px; height: 340px; } /style换数据就改CATEGORIESname是 x 轴的分类value是三角高度color是三角和图例的颜色。y 轴的最大值不用手改AXIS_MAX会取当前数据的最大值上浮一点再向上取整到刻度间隔的整数倍保证最高的三角上方留一截空隙不会尖顶贴到轴线顶端。这里 86 × 1.1 94.6向上取整到 20 的倍数就是 100刻度是 20 / 40 / 60 / 80 / 100。运行方式环境要求Vue3 项目 echarts5.5.1npm install echarts --save。跑起来把「四、完整示例」那份 SFC 存成PeakShape.vue页面里引入即可容器高度给 340px宽度随父级。换数据只改CATEGORIES一项 ——name是分类、value是三角高度、color是颜色。不装 Vue 也能先看效果把 option 整段丢进官方示例编辑器就能跑。五、可能出现的问题踩坑记录1、五个三角一样高symbolSize的高度写成了固定像素比如[72, 30]。它一旦跟数值脱钩82 和 63 画出来就是同一个高度。高度必须写100%意思是「跟柱体一样长」也就是从 0 长到数值。反过来要是看到某一个位置上叠了好几个三角多半是data没把其余位置写成null五条 series 全画在同一格上了。2、tooltip 一次弹出五行没值的显示成-trigger: axis会把这条轴上的所有series 都列出来。完整示例里自己写了formatter先filter掉null/undefined再拼字符串所以停在哪个分类就只弹哪一行。3、控制台报 Cant get DOM width or heightecharts.init之前容器必须有确定的宽高而且 DOM 已经挂载完。Vue 里包在onMountedawait nextTick()里最稳height: 0、或者挂在display: none的元素上初始化一定报这个错。4、切页面回来图表变白窗口缩放图表不跟着变两份原因凑在一起了实例没销毁、resize监听没摘。onBeforeUnmount里把window.removeEventListener(resize, handleResize)和myChart?.dispose()都补上myChart记得置回null。5、改了轴线的颜色轴上的文字跟着一起变浅axisLabel不写color时会继承同一根轴axisLine.lineStyle.color。完整示例里xAxis.axisLine配了浅灰#e0e0e0整排分类名就被带成同样的浅灰几乎看不清。yAxis没配axisLine躲过了这一条但会退到 ECharts 默认的灰蓝#6E7079和顶部数值、图例的#333333摆在一起仍浅一档 —— 所以完整示例里两根轴都显式写了color: #333333。要么别给axisLine上色要么给axisLabel显式写上颜色。结语三角山峰图就三件事pictorialBarsymbol: triangle是山symbolSize高度写100%让它跟着数值长图例要分开就一个分类一条 series、其余位置填null。最容易翻车的是第一条 —— 高度写死像素五个分类画成一个高度。欢迎关注【前端小知识营地】