ECharts 折线图
这个小节开始我们开始学习 ECharts 中的各个图形,这些图形都有着自己独特的风格,有着自己更适合的场景,在合理的场景下选择更为合适的图才能让我们的数据更好展示与分析。本节我们就先讲折线图这个稍微简单的图形。折线图用于显示数据在一个连续的时间间隔或者时间跨度上的变化,它的特点是反映事物随另一维度数值变化所产生趋势。
1. 简介
官方定义:
折线图是用折线将各个数据点标志连接起来的图表,用于展现数据的变化趋势。可用于直角坐标系和极坐标系上。
慕课解释
折线图是用直线将一系列的数据点连接的图表,可以显示随维度 x 变化而变化的 y 数据,适合用于显示在相同 x 间隔下,数据的变化趋势。ECharts 的提供的折线图功能非常完备,可通过配置项的 series 属性传入 type = line
的对象完成配置。
折线图配置项繁多,官网 对此已有详尽介绍,在此不赘述。下面会提供丰富的示例,详尽介绍折线图的方方面面。
2. 实例解说
2.1 基础示例
在 echarts 中,通过传入 xAxis、yAxis、series 三个关键属性,即可完成一个折线图的配置,示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
示例代码有几个关键点:
- 需要传入 xAxis 显式声明 x 轴状态,示例中通过
type: category
将该轴配置为类目轴,并通过 data 属性显式定义该轴下的类目数据; - 需要传入 yAxis 显式声明 y 轴状态,示例中通过
type: value
将盖州配置为类目轴; - 折线图通过配置项的 series 传入,且必须声明
type: line
。示例中通过 data 属性声明了该图表的系列数据。
实际应用中,我们常常会忽略类目轴的 data 配置,而交由 echarts 自行推断,下例代码可以实现与上例相同的效果:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
},
yAxis: {
type: 'value',
},
series: [
{
data: [
['Mon', 820],
['Tue', 932],
['Wed', 901],
['Thu', 934],
['Fri', 1290],
['Sat', 1330],
['Sun', 1320],
],
type: 'line',
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
2.2 双轴折线图
有时候,需要在一个图表上显示多个系列的数据,但如果数据之间的范围偏差比较大,较小的部分就可能会被拉伸到接近直线,丢失了变化趋势的表达能力,例如:
图中,红色系列的数据为 [820, 932, 901, 934, 1290, 1330, 1320],但因为蓝色系列的数值过大:[14080, 13800, 12380, 15860, 13380, 14900, 15108],使得折线图上表现得接近一条水平线。此时,可通过设置两个 y 轴,让坐标轴呈现的数值范围更接近于真实数据范围,示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: [{ type: 'value' }, { type: 'value' }],
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
},
{
data: [14080, 13800, 12380, 15860, 13380, 14900, 15108],
type: 'line',
yAxisIndex: 1,
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
相比于第一张图,新的折线图更能传达出数据变化的趋势。从代码看,一是需要在 yAxis 配置上传入两个配置项;二是需要在 series 配置上,指明序列对应的 yAxisIndex 属性,以区分序列所对应的的坐标轴。
除了拆分坐标轴外,也可以选择拆分整个坐标系,画成两个不同的图表:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
// 拆分多个坐标系
grid: [
{ left: 50, right: 50, height: '35%' },
{ left: 50, right: 50, top: '55%', height: '35%' },
],
xAxis: [
{
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
{
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
// 指明归属于那个坐标系
gridIndex: 1,
postion: 'top',
},
],
yAxis: [
{ type: 'value' },
// 指明归属于那个坐标系
{ type: 'value', gridIndex: 1, inverse: true },
],
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
},
{
data: [14080, 13800, 12380, 15860, 13380, 14900, 15108],
type: 'line',
yAxisIndex: 1,
xAxisIndex: 1,
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
示例中,grid、xAxis、yAxis 均声明了两份配置,从而拆分出两个分离的坐标系,这种表现方法可以在有限的面积内清晰表现出多份关联数据,日常开发中经常会用到。
3. 配置详解
3.1 data 数据配置项详解
data 属性用于配置折线图的数据集,上面例子已经给出一些示例。data 项的常见形态有:
- 空值: 当某数据不存在时,可以用 ‘-’、null、undefined、NaN 表示;
- 二维数组: 数组项用一个二维数组表示: [x, y],在直角坐标系中对应 [x值, y值];在极坐标系中对应 [距离, 角度];
- 一维数组: 数组项用一个数字表示,通常见于直角坐标系上某一轴为类目轴的场景。 data 值与 axis 值按顺序一一对应,例如:
{ "xAxis": { "type": "category", "data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] }, "series": [ { // 对应顺序: // Mon Tue Wed Thu Fri Sat Sun "data": [820, 932, 901, 934, 1290, 1330, 1320] } ] }
- 对象: 数组项用一个对象表示,例如:
{ "xAxis": { "type": "category" }, "data": [ { "name": "Mon", "value": 820 }, { "name": "Tue", "value": 932 }, { "name": "Wed", "value": 901 }, { "name": "Thu", "value": 934 }, { "name": "Fri", "value": 1290 }, { "name": "Sat", "value": 1330 }, { "name": "Sun", "value": 1320 } ] }
当数组项为对象时,除 name、value 属性外还可以传入 symbol、label 等配置项实现针对数据项级别的定制化,例如:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [
// 数字
932,
// 二维数组
['Mon', 820],
// 空值
'-',
// 对象
{ name: 'Thu', value: 934 },
// 支持更多属性
{ name: 'Fri', value: 1290, label: { position: 'top', color: '#000' } },
1330,
1320,
],
type: 'line',
label: { show: true, position: 'bottom' },
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
3.2 symbol 配置详解
symbol 用于描述图表上点的绘制方法,对应下图红色圆点部分:
在 ECharts 上,symbol 可通过如下配置项描述:
配置名 | 类型 | 默认值 | 说明 |
---|---|---|---|
showSymbol | boolean | true | 控制是否显示 symbol, 如果 false 则只有在 tooltip hover 的时候显示。 |
showAllSymbol | boolean|string | auto | 控制标记的显示策略,只在主轴为类目轴(axis.type 为 ‘category’)时有效。 |
symbol | string|function | emptyCircle | 标记的图形 |
symbolSize | number|array|function | 4 | 控制标记符号的大小 |
symbolRotate | number | 0 | 标记的旋转角度 |
symbolKeepAspect | boolean | true | 如果 symbol 是 path:// 形式,是否在缩放时保持该图形的长宽比。 |
symbolOffset | array | [0, 0] | 标记相对于原本位置的偏移 |
通过上述配置,可以改变图表上点的表现形式,接下来就表中关键事项展开示例。
3.2.1 使用预设标记图形
默认的,ECharts 会使用空心圆绘制标记点,如上一节示例图所示。除空心圆外,ECharts 还准备了几个开箱即用的标记图形选项,完整列表包括:
- emptyCircle:空心圆
- circle:实心圆
- rect:正方形
- roundRect:圆角正方形
- triangle:三角形
- diamond:棱形
- pin:水滴
- arrow:箭头
- none:无图形,形如设置 showSymbol:false
各选项对应的展示效果如下:
3.2.2 使用自定义标记
除预设的图形集合外,echarts 支持自定义标记图形,同样通过 symbol 属性定义,支持传入 3 种值:
- 支持
image://http://xxx/xxx.png
格式,传入标记图形的 URL; - 支持
image://data:image/png;base64,ixxx
格式,传入标记图形的 Base64 值; - 支持
path://M30.9,53.2C16.8...
格式,传入标记图形的 svg 路径值。
示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var symbols = [
// 传入图片地址
{ symbol: 'image://' + location.origin + '/assets/imooc-logo.png', name: 'imooc' },
{
// 传入图片base64
name: 'echarts',
symbol:
'image://data:image/png;base64,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',
},
{
// 传入图形路径
name: 'SVG 路径',
symbol:
'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z',
},
{ symbol: 'rect', name: '原生 rect' },
];
var index = 0;
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
},
yAxis: {
type: 'value',
},
series: [
{
data: symbols.map((v, i) => [v.name, i * 10 + 10]),
showSymbol: true,
type: 'line',
label: {
normal: {
show: true,
position: 'bottom',
formatter: '{b}',
},
},
symbol(v) {
var s = symbols[index++];
return s.symbol;
},
symbolSize: 40,
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
3.2.3 控制显示
当类目轴上数据太多时,可能导致标记的展示特别拥挤,ECharts 就此提供了 showAllSymbol 配置项,该项接受如下值:
- auto:默认值,如果有足够空间则显示标志图形,否则随主轴标签间隔隐藏策略;
- true:显示所有图形;
- false:随主轴标签间隔隐藏策略。
示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 800px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var len = 100;
var data = [];
for (var i = 0; i < len; i++) {
data.push(['分类 ' + i, Math.random() * 100]);
}
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
grid: [
{ left: 40, top: 50, width: '40%' },
{ left: '54%', top: 50, width: '40%' },
],
title: [
{ left: 40, text: 'showAllSymbol = true', top: 10 },
{ left: '54%', text: 'showAllSymbol = false', top: 10 },
],
xAxis: [{ type: 'category' }, { type: 'category', gridIndex: 1 }],
yAxis: [{ type: 'value' }, { type: 'value', gridIndex: 1 }],
series: [
{
data: data,
showSymbol: true,
type: 'line',
symbol: 'rect',
symbolSize: 10,
showAllSymbol: true,
},
{
data: data,
showSymbol: true,
type: 'line',
symbol: 'rect',
symbolSize: 10,
showAllSymbol: false,
xAxisIndex: 1,
yAxisIndex: 1,
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
对比可知,左图 showAllSymbol = true
时,显示所有标记图形,略显拥挤;右图 showAllSymbol = false
,则随主轴标记隐藏而隐藏。
3.3 label 配置详解
label 项用于配置折线图点上的文本标签,支持显示点的系列名、数据名、数据值以及其他自定义信息。与 tooltip 不同,label 显示的文本信息与折线上的点强相关,通常配置在点的附近显示,例如:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
label: { show: true, position: 'top' },
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
3.3.1 配置标签位置
可通过如下配置项设定标签的显示位置:
配置名 | 类型 | 默认值 | 说明 |
---|---|---|---|
position | string|array | top | 标签位置,支持数组与字符串类型,默认为 top 即坐标点上方 |
distance | number | 5 | 标签与坐标点的距离,仅当 position 为字符串选项值时有效 |
rotate | number | 标签选择角度 | |
offset | array | [0, 0] | 标签距离默认位置的偏移值 |
其中, position 支持数组如 [10, 30] 用于指定像素位置值,或如 [10%, 20%]
用于指定百分比位置值。此外,还支持如下枚举值:
- top
- left
- right
- bottom
- inside
- insideLeft
- insideRight
- insideTop
- insideBottom
- insideTopLeft
- insideBottomLeft
- insideTopRight
- insideBottomRight
枚举值对应位置如图:
position 属性决定了标签的大致位置,之后可以通过配置其他位置属性做出微调,如下示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
label: { show: true, position: 'bottom', distance: -10 },
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
3.3.2 配置标签内容
可通过 label.formatter
属性修改折线图标签内容,支持模板字符串与回调函数两种形式。模板字符串支持如下变量:
{a}
:系列名;{b}
:数据名;{c}
:数据值。{@xxx}
:数据中名为’xxx’的维度的值,如{@product}
表示名为 ‘product’ 的维度的值;{@[n]}
:数据中维度 n 的值,如{@[3]}
表示维度 3 的值,从 0 开始计数。
标签内容默认只展示数据值,相当于 {c}
。模板字符串方式的配置相对来说更加清晰简单,例如:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [
['Mon', 820, 1],
['Tue', 932, 2],
['Wed', 901, 3],
['Thu', 934, 4],
['Fri', 1290, 5],
['Sat', 1330, 6],
['Sun', 1320, 7],
],
type: 'line',
label: {
show: true,
position: 'bottom',
formatter: '{b}: {@[1]}\n{@[2]}',
},
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
回调函数方式支持传入格式化函数,函数将收到当前数据项的描述对象作为参数,形如:
{
componentType: 'series',
// 系列类型
seriesType: string,
// 系列在传入的 option.series 中的 index
seriesIndex: number,
// 系列名称
seriesName: string,
// 数据名,类目名
name: string,
// 数据在传入的 data 数组中的 index
dataIndex: number,
// 传入的原始数据项
data: Object,
// 传入的数据值。在多数系列下它和 data 相同。在一些系列下是 data 中的分量(如 map、radar 中)
value: number|Array|Object,
// 坐标轴 encode 映射信息,
// key 为坐标轴(如 'x' 'y' 'radius' 'angle' 等)
// value 必然为数组,不会为 null/undefied,表示 dimension index 。
// 其内容如:
// {
// x: [2] // dimension index 为 2 的数据映射到 x 轴
// y: [0] // dimension index 为 0 的数据映射到 y 轴
// }
encode: Object,
// 维度名列表
dimensionNames: Array<String>,
// 数据的维度 index,如 0 或 1 或 2 ...
// 仅在雷达图中使用。
dimensionIndex: number,
// 数据图形的颜色
color: string,
}
函数方式更灵活,适合用于描绘复杂标签的场景,例如计算系列上每个节点数值在整个系列的百分比,示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var data = [
['Mon', 820],
['Tue', 932],
['Wed', 901],
['Thu', 934],
['Fri', 1290],
['Sat', 1330],
['Sun', 1320],
];
var total = data.reduce((r, row) => r + row[1], 0);
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: data,
type: 'line',
label: {
show: true,
position: 'bottom',
formatter(obj) {
var data = obj.data;
var v = data[1];
// 计算百分比
var percent = ((v / total) * 100).toFixed(2);
return data[0] + ': ' + v + '\n' + percent + '%';
},
},
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例效果:
4. 个人经验
折线图形式简单,内容清晰,简明易懂,经常用于表达数据序列的 连续变化,例如 UV/PV 趋势、流量变化、活跃度等,在实战中使用的频率比较高。echarts 的折线图提供了丰富的配置项,基本上能够覆盖日常大多数场景,甚至可以说,当你觉得无法满足需求的时候,不妨回过头来看看配置问题,或许某个配置项上的小改动,就能解决问题。
echarts 的折线图提供了大量的配置,学习过程中需要多尝试,仔细阅读文档,多对比配置项不同值的效果的效果。
比如这样一个问题,当数据序列的数值离散程度低,表现得可能会接近一条直线,考虑数值序列 [10444, 10484, 10984, 10975, 10264, 10088, 10822, 10046, 10708, 10514],在默认情况下,表现如下:
解决问题先要理解问题症结,可以看到 y 坐标轴上预留了大量的空间留给 0 - 10000
数值范围,导致真正表现数据的 10000 - 11000
反而占据的空间很小。解决方法是适当设置 yAxis.min
属性,用序列数值来推断最小值,例如:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: 600px;height: 400px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.common.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
toolbox: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Day 1', 'Day 2', 'Day 3', 'Day 4', 'Day 5', 'Day 6', 'Day 7', 'Day 8', 'Day 9', 'Day 10'],
},
// 将y轴的min属性设置为 `dataMin`
// 交由 echarts 自行实现最小值的推断
yAxis: { type: 'value', min: 'dataMin' },
series: [
{
data: [10444, 10484, 10984, 10975, 10264, 10088, 10822, 10046, 10708, 10514],
type: 'line',
label: { show: true, position: 'bottom' },
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
这样看起来就顺眼多了。
5. 小结
本节结合实例讲述 Echarts 折线图的功能特性,包括基础配置方法;如何实现双轴折线图;如何实现极坐标折线图;以及折线图中其他配置属性的详细讨论。