ECharts 散点图
当我们的数据变得越来越复杂,需要展示和比较的变得越来越多,这个时候再使用简单的图形可能不能够表现出我们想展现的,这一节我们就来看一下在比较多数据维度的情况下比较合适的图形——散点图。散点图是用坐标系上的点表示多个事物的数值分布情况的图。
官方解释
散点(气泡)图。直角坐标系上的散点图可以用来展现数据的 x,y 之关系,如果数据项有多个维度,其它维度的值可以通过不同大小的 symbol 展现成气泡图,也可以用颜色来表现。
可以应用在直角坐标系、极坐标系、地图坐标系上。
解释
散点图,又称点图,是一种将离散数据以点的形式散布在坐标系上的图表,每个数据节点通过坐标位置或散点本身的大小、颜色等视觉表达节点数值情况。相比于折线图,散点图更偏重于表达数据的离散分布,比如班的考试成绩的分布就非常适合用散点图。
勾画直角坐标系下的散点图,最简情况下需要配置:yAxis
、xAxis
、series
,示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
< charset="utf-8" />
< http-equiv="X-UA-Compatible" content="IE=edge" />
< name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: px;height: px"></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 = {
tool@R_610_2@: {
feature: {
saveAsImage: {},
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [
['Mon', ],
['Tue', ],
['Wed', ],
['Thu', ],
['Fri', ],
['Sat', ],
['Sun', ],
],
type: 'scatter',
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例:
与 相似,但散点图比折线图强大的地方在于,它可以通过颜色、大小表达出更多维度的信息。简单,可以通过 symbolSize
点的大小,该接受如下值:
在上例基础上, series
配置如下:
{
series: [
{
data: [
['Mon', 120, 224],
['Tue', 80, 320],
['Wed', 140, 1288],
['Thu', 192, 64],
['Fri', 140, 228],
['Sat', 180, 248],
['Sun', 178, 240],
],
type: 'scatter',
symbolSize: function (data) {
return Math.sqrt(data[2]);
},
},
],
}
一是在 data 序列上第三个维度;二是 symbolSize
配置项,通过计算出各节点大小。示例:
还可以通过散点上不同的颜色,表现多维数据,简单可通过 itemStyle.color
配置各节点颜色。在上例基础上, series
配置如下:
{
series: [
{
data: [
['Mon', 120, 224],
['Tue', 80, 320],
['Wed', 140, 1288],
['Thu', 192, 64],
['Fri', 140, 228],
['Sat', 180, 248],
['Sun', 178, 240],
],
type: 'scatter',
itemStyle: {
color: function (node) {
return `hsla(${node.data[2] % 360}, 100%, 50%, 0.8)`;
},
},
},
],
}
示例:
注意,上述示例需要手动计算每个节点的颜色、大小,这部分逻辑在散点图内部会有更好的实现,只需配合使用 visualMap
即可,下面会有详细介绍。
极坐标配置与直角坐标相似,示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
< charset="utf-8" />
< http-equiv="X-UA-Compatible" content="IE=edge" />
< name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: px;height: px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
tool@R_610_2@: {
feature: {
saveAsImage: {},
},
},
polar: {},
angleAxis: {
type: 'category',
startAngle: ,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
radiusAxis: { type: 'value' },
series: [
{
coordinateSy: 'polar',
data: [
[, 'Mon'],
[, 'Tue'],
[, 'Wed'],
[, 'Thu'],
[, 'Fri'],
[, 'Sat'],
[, 'Sun'],
],
type: 'scatter',
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
示例:
类似的,可以通过 symbolSize
配置散点大小。在上例基础上, series
配置:
{
series: [
{
coordinateSy: 'polar',
data: [
[120, 'Mon', 224],
[80, 'Tue', 320],
[140, 'Wed', 1288],
[192, 'Thu', 64],
[140, 'Fri', 228],
[180, 'Sat', 248],
[178, 'Sun', 240],
],
type: 'scatter',
symbolSize: function (data) {
return Math.sqrt(data[2]);
},
},
],
}
示例:
可以通过 itemStyle.color
散点颜色。在上例基础上, series
配置:
{
series: [
{
coordinateSy: 'polar',
data: [
[120, 'Mon', 224],
[80, 'Tue', 320],
[140, 'Wed', 1288],
[192, 'Thu', 64],
[140, 'Fri', 228],
[180, 'Sat', 248],
[178, 'Sun', 240],
],
type: 'scatter',
itemStyle: {
color: function (node) {
return `hsla(${node.data[2] % 360}, 100%, 50%, 0.8)`;
},
},
},
],
}
示例:
日历坐标系是在日历图中通过颜色、图形、连线等方式表达数据变化,特别适用于与时间强相关的数据序列。github 上的 contributions 分布图就是典型的日历图示例:
日历坐标系同样散点图,示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
< charset="utf-8" />
< http-equiv="X-UA-Compatible" content="IE=edge" />
< name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: px;height: px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.js"></script>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var option = {
tool@R_610_2@: {
feature: {
saveAsImage: {},
},
},
calendar: {
top: 'middle',
left: 'center',
cellSize: ,
range: ['2019-02-01', '2019-03-31'],
},
series: [
{
type: 'scatter',
coordinateSy: 'calendar',
symbolSize: ,
calendarIndex: ,
symbolSize: function (data) {
return Math.sqrt(data[]);
},
itemStyle: {
color: function (node) {
return `hsla(${node.data[] % }, 100%, 50%, 0.8)`;
},
},
data: [
[, ],
[new Date(, , ), ],
[new Date(, , ), ],
[new Date(, , ), ],
[new Date(, , ), ],
[new Date(, , ), ],
[new Date(, , ), ],
],
},
],
};
myChart.setOption(option);
</script>
</body>
</html>
需要注意,日历坐标系下的散点图数据 data
需要使用二维数组指定每个项的值,数组第一项指明数据所在的时间,通常使用 Date
对象或时间戳;第二项指明数据值。上例:
ECharts 中的散点图带涟漪特效动画,不过被实现为另外一种图表类型 series.type = effectScatter
。涟漪特效会在数据点上周期执行动画,类似于:
实际上,虽然图表类型不同,effectScatter
完全继承了 scatter
的配置项 —— 也就意味着 effectScatter
所有 scatter
的。完整配置请参考 ,其中与涟漪有关的配置项有:
如果散点图中数据量比较大,而又希望读者重点关注某系列数据时,可以配合使用基础散点图与涟漪散点图,利用涟漪图的动画吸引的注意力,例如:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
< charset="utf-8" />
< http-equiv="X-UA-Compatible" content="IE=edge" />
< name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<div id="main" style="width: px;height: px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.js"></script>
<script type="text/javascript">
// 数据
function generateData(cats) {
const random = (min, max) => Math.round(Math.random() * (max - min) + min);
const series = [
{ name: '我司', type: 'effectScatter' },
{ name: '竞品1', type: 'scatter' },
{ name: '竞品2', type: 'scatter' },
{ name: '竞品3', type: 'scatter' },
];
return series.map((serie) => ({
...serie,
data: cats.map((cat) => [cat, random(, )]),
}));
}
const myChart = echarts.init(document.getElementById('main'));
const cats = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
const series = generateData(cats);
var option = {
xAxis: { type: 'category', data: cats },
yAxis: { type: 'value' },
series: series,
legend: { data: series.map((s) => s.name) },
};
myChart.setOption(option);
</script>
</body>
</html>
示例:
还可以通过 rippleEffect
项定制涟漪,例如上例基础上涟漪图配置为:
{
type: 'effectScatter',
rippleEffect: {
period: ,
scale: ,
brushType: ''
}
},
示例:
ECharts 4 之后,如果需要渲染的图形数据太多而出现卡顿时,可以通过设置 large = true
开启渐进渲染。原理上,当数据量达到几千、几万时,如果要一次性渲染这么多图形可能会造成卡顿甚至假死,ECharts 通过将需要渲染的数据按特定算法分成多个批次,每次渲染批次的数据量,尽可能快地渲染出一部分数据,减少卡顿感。下列用于配置渐进渲染的细节:
启动渐进渲染的很简单,只需要设置 large = true
,当数据量超过 largeThreshold
设定的阈值时,ECharts 就会启动渐进渲染,例如下例中渲染 500000 数据:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
< charset="utf-8" />
< http-equiv="X-UA-Compatible" content="IE=edge" />
< name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Echarts Example</title>
</head>
<body>
<button id="btnStart" type="button">开始渲染</button>
<div id="main" style="width: px;height: px"></div>
<script src="//cdn.bootcss.com/echarts/4.5.0/echarts.js"></script>
<script type="text/javascript">
// 数据
function genData(len, offset) {
const lngRange = [-, ];
const latRange = [, ];
const result = new Array(len);
for (let i = ; i < len; i++) {
const x = +Math.random() * ;
const y = +Math.sin(x) - x * (len % ? : -) * Math.random() + (offset || ) / ;
result[i] = [x, y];
}
return result;
}
const data = genData();
const chart = echarts.init(document.getElementById('main'));
const option = {
xAxis: { type: 'value' },
yAxis: { type: 'value' },
series: [
{
data: data,
type: 'scatter',
large: true,
largeThreshold: ,
progressive: ,
symboleSize: ,
},
],
};
document.getElementById('btnStart').addEventListener('click', function () {
chart.setOption(option);
});
</script>
</body>
</html>
示例: