Table of Contents
部分地址
文档:http://echarts.baidu.com/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts
示例集合:http://echarts.baidu.com/examples/index.html
主题编辑器:http://echarts.baidu.com/theme-builder/
ECharts 特性
ECharts 兼容对当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖轻量级的矢量图形库 ZRender。
丰富的可视化类型
ECharts 提供了常规的折线图、柱状图、散点图、饼图、K线图,用于统计的盒形图,用于地理数据可视化的地图、热力图、线图,用于关系数据可视化的关系图、treemap、旭日图,多维数据可视化的平行坐标,还有用于 BI 的漏斗图,仪表盘,并且支持图与图之间的混搭。
除了已经内置的包含了丰富功能的图表,ECharts 还提供了自定义系列,只需要传入一个renderItem函数,就可以从数据映射到任何你想要的图形,更棒的是这些都还能和已有的交互组件结合使用而不需要操心其它事情。
多种数据格式无需转换直接使用
ECharts 内置的 dataset 属性(4.0+)支持直接传入包括二维表,key-value 等多种格式的数据源,为了配合大数据量的展现,ECharts 还支持输入 TypedArray 格式的数据。
千万数据的前端展现
通过增量渲染技术(4.0+),配合各种细致的优化,ECharts 能够展现千万级的数据量,并且在这个数据量级依然能够进行流畅的缩放平移等交互。
几千万的地理坐标数据就算使用二进制存储也要占上百 MB 的空间。因此 ECharts 同时提供了对流加载(4.0+)的支持,你可以使用 WebSocket 或者对数据分块后加载,加载多少渲染多少!不需要漫长地等待所有数据加载完再进行绘制。
移动高端优化
细粒度的模块化和打包机制可以让 ECharts 在移动端也拥有很小的体积,可选的 SVG 渲染模块让移动端的内存占用不再捉襟见肘。
多渲染方案,跨平台使用
ECharts 支持以 Canvas、SVG(4.0+)、VML 的形式渲染图表。VML 可以兼容低版本 IE,SVG 使得移动端不再为内存担忧,Canvas 可以轻松应对大数据量和特效的展现。
深度的交互式数据探索
提供了 图例、视觉映射、数据区域缩放、tooltip、数据刷选等开箱即用的交互组件,可以对数据进行多维度数据筛取、视图缩放、展示细节等交互操作。
多维数据的支持以及丰富的视觉编码手段
ECharts 3 开始加强了对多维数据的支持。除了加入了平行坐标等常见的多维数据可视化工具外,对于传统的散点图等,传入的数据也可以是多个维度的。配合视觉映射组件 visualMap 提供的丰富的视觉编码,能够将不同维度的数据映射到颜色,大小,透明度,明暗度等不同的视觉通道。
动态数据
根据数据变化通过合适的动画展现。配合 timeline 组件能够在更高的时间维度上去表现数据的信息。
绚丽的特效
ECharts 针对线数据,点数据等地理数据的可视化提供了吸引眼球的特效。
通过 GL 实现更多更强大绚丽的三维可视化
提供了基于 WebGL 的 ECharts GL.
无障碍访问(4.0+)
支持自动根据图表配置项智能生成描述,使得盲人可 以在朗读设备的帮助下了解图表内容,让图表可以被更多人群访问!
ECharts 教程
5 分钟上手 ECharts
获取 ECharts
- 官网
- GitHub
- npm install echarts –save
- cdn
引入 ECharts
ECharts 3 开始不再强制使用 AMD 方式按需引入,因此可以通过 script
标签引入。
绘制一个简单的图表
绘制前准备一个容器。
<body> <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM --> <div id="main" style="width: 600px;height:400px;"></div> </body>
通过 echarts.init
初始化一个实例,并通过 setOption
方法生成一个简单的柱状图。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts</title> <!-- 引入 echarts.js --> <script src="echarts.min.js"></script> </head> <body> <!-- 为ECharts准备一个具备大小(宽高)的Dom --> <div id="main" style="width: 600px;height:400px;"></div> <script type="text/javascript"> // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('main')); // 指定图表的配置项和数据 var option = { title: { text: 'ECharts 入门示例' }, tooltip: {}, legend: { data:['销量'] }, xAxis: { data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); </script> </body> </html>
自定义构建 ECharts
- 在线自定义构建
- 使用
echarts/build/build.js
脚本自定义构建 - 直接使用构建工具(如 rollup、webpack、browserify) 自己构建
准备工作:创建自己的工程和安装 echarts
使用 ES Module:
import * as echarts from 'echarts';
使用 CommonJS:
var echarts = require('ehcarts');
使用 echarts 提供的构建脚本自定义构建
构建一个只含有饼图的文件。
node node_modules/echarts/build/build.js --help
该例中用到的参数有:
- -i:代码入口文件,可以是绝对路径或者基于当前命令行路径的相对路径。
- -o:生成的 bundle 文件,可以是绝对路径或者基于当前命令行路径的相对路径。
- –min:是否压缩文件(默认不压缩),并且去多余的打印错误信息的代码,形成生产环境可用的文件。
- –lang <language shortcut or file path>:是否使用其他语言版本,默认是中文。例如:–lang en 表示使用英文,–lang my/langXX.js 表示构建时使用 <cwd>/my/langXX.js 替代 echarts/lib/lang.js 文件。
- –sourcemap:是否输出 source map,以便于调试。
- –format:输出的格式,可选 ‘umb’(默认)、’amd’、’iife’、’cjs’、’es’。
入口文件可以命名为:myProject/echarts.custom.js
// 引入 echarts 主模块。 export * from 'echarts/src/echarts'; // 引入饼图。 import 'echarts/src/chart/pie'; // 在这个场景下,可以引用 `echarts/src` 或者 `echarts/lib` 下的文件(但是不可混用), // 参见下方的解释:“引用 `echarts/lib/**` 还是 `echarts/src/**`”。
然后命令行
node node_modules/echarts/build/build.js --min -i echarts.custom.js -o lib/echarts.custom.min.js
允许被引用的模块
在自定义构建中,允许被引用的模块,全声明在 myProject/node_module/echarts/echarts.all.js
和 myProject/node_module/echarts/src/export.js
中。echarts 和 zrender 源代码中的其他模块,都是 echarts 的内部模块,不应该去引用。因为在后续 echarts 版本升级中,内部模块的接口和功能可能变化,甚至模块本身也可能被移除。
引用 echarts/lib/** 还是 echarts/src/**
- 项目中如果直接引用 echarts 里的一些模块并自行构建,应该使用
echarts/lib/**
路径,而不可使用echarts/src/**
。 - 当使用构建脚本
echarts/build/build.js
打包 bundle,那么两者可以选其一使用(不可混用),使用echarts/src/**
可以获得稍微小一些的文件体积。
直接使用 rollup 自定义构建
// 引入 echarts 主模块。 import * as echarts from 'echarts/lib/echarts'; // 引入折线图。 import 'echarts/lib/chart/line'; // 引入提示框组件、标题组件、工具箱组件。 import 'echarts/lib/component/tooltip'; import 'echarts/lib/component/title'; import 'echarts/lib/component/toolbox'; // 基于准备好的dom,初始化 echarts 实例并绘制图表。 echarts.init(document.getElementById('main')).setOption({ title: {text: 'Line Chart'}, tooltip: {}, toolbox: { feature: { dataView: {}, saveAsImage: { pixelRatio: 2 }, restore: {} } }, xAxis: {}, yAxis: {}, series: [{ type: 'line', smooth: true, data: [[12, 5], [24, 20], [36, 36], [48, 10], [60, 10], [72, 20]] }] });
然后根据配置文件构建。参考 rollup 或者 webpack
的使用。
多语言支持
语言可以通过 option
定制。但如果想“默认就是某种语言”,则需要通过构建来实现。
在上面的例子中,可以在 echarts/build/build.js
的参数中指定语言:
node node_modules/echarts/build/build.js --min -i echarts.custom.js -o lib/echarts.custom.min.js --lang en
表示使用内置的英文。此外还可以是 --lang fi。
node node_modules/echarts/build/build.js --min -i echarts.custom.js -o lib/echarts.custom.min.js --lang my/langXX.js
表示在构建时使用 myProject/my/langXX.js
文件来替换 myProject/node_modules/echarts/lib/lang.js
文件。这样可以在 myProject/my/langXX.js
文件中自定义语言。注意这种方式中,必须指定 -o
或者 --output
。
在 webpack 中使用 ECharts
在 webpack 中使用 ECharts
npm 安装 EChatrs
npm install ehcarts --save
引入 ECharts
var echarts = require('echarts'); // 基于准备好的dom,初始化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] }] });
按需引入 ECharts 图表和组件
默认使用 require(‘echarts’) 得到的是已经加载了所有图表和组件的 ECharts 包,因此体积会比较大,如果在项目中对体积要求比较苛刻,也可以只按需引入需要的模块。
例如上面示例代码中只用到了柱状图,提示框和标题组件,因此在引入的时候也只需要引入这些模块,可以有效的将打包后的体积从 400 多 KB 减小到 170 多 KB。
// 引入 ECharts 主模块 var echarts = require('echarts/lib/echarts'); // 引入柱状图 require('echarts/lib/chart/bar'); // 引入提示框和标题组件 require('echarts/lib/component/tooltip'); require('echarts/lib/component/title'); // 基于准备好的dom,初始化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] }] });
可以按需引入的模块列表见:
https://github.com/ecomfe/echarts/blob/master/index.js
个性化图表的样式
ECharts 提供了丰富的自定义配置选项,并且能够从全局、系列、数据三个层级去设置数据图形的样式。
绘制南丁格尔图
这次要画的是饼图,它的数据格式比柱状图更简单,只有一维的数值,不需要给类目。因为不再直角坐标系上,所以也不需要 xAxis
,yAxis
。
<body> <div id="main"></div> <script> let myChart = echarts.init(document.getElementById('main')); myChart.setOption({ series: [ { name: '访问来源', type: 'pie', radius: '55%', data: [ {value: 235, name: '视频广告'}, {value: 274, name: '联盟广告'}, {value: 310, name: '邮件营销'}, {value: 335, name: '直接访问'}, {value: 400, name: '搜索引擎'} ] } ] }); </script> </body>
ECharts 中的数据项都是既可以只设成数值,也可以设成一个包含有名称、该数据图形的样式配置、标签配置的对象,具体见 data 文档。ECharts 中的饼图也支持通过设置 roseType
显示成南丁格尔图。
roseType: 'angle'
:通过半径表示数据的大小。
阴影的配置
ECharts 中有一些通用的样式,诸如阴影、透明度、颜色、边框颜色、边框宽度等,这些样式一般都会在系列的 itemStyle 里设置。例如阴影的样式可以通过下面几个配置项设置:
itemStyle: { // 阴影的大小 shadowBlur: 200, // 阴影水平方向上的偏移 shadowOffsetX: 0, // 阴影垂直方向上的偏移 shadowOffsetY: 0, // 阴影颜色 shadowColor: 'rgba(0, 0, 0, 0.5)' }
深色背景和浅色标签
背景色是全局的,所以直接在 option 下设置 backgroundColor
setOption({ backgroundColor: '#2c343c' })
文本的样式可以设置全局的 textStyle
setOption({ textStyle: { color: 'rgba(255, 255, 255, 0.3)' } })
也可以每个系列分别设置,每个系列的文本设置在 label.textStyle
label: { textStyle: { color: 'rgba(255, 255, 255, 0.3)' } }
饼图的话还要将标签的视觉引导线的颜色设置为浅色。
labelLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } }
设置扇形的颜色
扇形的颜色也是在 itemStyle 中设置
itemStyle: { // 设置扇形的颜色 color: '#c23531', shadowBlur: 200, shadowColor: 'rgba(0, 0, 0, 0.5)' }
ECharts 中每个扇形颜色的可以通过分别设置 data 下的数据项实现。
data: [{ value:400, name:'搜索引擎', itemStyle: { color: '#c23531' } }, ...]
但这次因为只有明暗度的变化,所以有一种更快捷的方式是通过 visualMap 组件将数值的大小映射到明暗度。
visualMap: { // 不显示 visualMap 组件,只用于明暗度的映射 show: false, // 映射的最小值为 80 min: 80, // 映射的最大值为 600 max: 600, inRange: { // 明暗度的范围是 0 到 1 colorLightness: [0, 1] } }
百度示例地址:http://www.echartsjs.com/gallery/editor.html?c=doc-example/tutorial-styling-step5
ECharts 中的样式简介
本文主要是大略概述,用哪些方法,可以设置样式,改变图形元素或者文字的颜色、明暗、大小等。本文介绍的这几种方式,他们的功能范畴可能会有交叉(即同一种细节的效果可能可以用不同的方式实现),但是他们各有各的场景偏好。
- 颜色主题(Theme)
- 调色盘
- 直接样式设置(itemStyle,lineStyle,areaStyle,label……)
- 视觉映射(visualMap)
颜色主题(Theme)
示例集合:http://echarts.baidu.com/examples/index.html
ECharts4 开始,内置了三套主题:‘default’,‘light’,‘dark’
var chart = echarts.init(dom,'light');
或者
var char = echarts.init(dom, 'dark');
其他的主题需要自己加载。
主题编辑器:http://echarts.baidu.com/theme-builder/
如果主题保存为 JSON 格式,可以自行加载和注册:
// 假设主题名称是“vintage” $.getJSON("xxx/xxx/vintage.json",function(themeJSON){ echarts.registerTheme('vintage',JSON.parse(themeJSON)); var chart = echarts.init(dom,'vintage'); });
如果保存为 UMD 格式的 js 文件,那么支持自注册。直接引入 JS 文件即可。
// HTML 引入 vintage.js 文件后(假设主题名称是 "vintage") var chart = echarts.init(dom, 'vintage'); // ...
调色盘
调色盘,可以在 option 中设置。它给定了一组颜色,图形、系列会自动从其中选择颜色。 可以设置全局的调色盘,也可以设置系列自己专属的调色盘。
option = { // 全局调色盘。 color: ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3'], series: [{ type: 'bar', // 此系列自己的调色盘。 color: ['#dd6b66','#759aa0','#e69d87','#8dc1a9','#ea7e53','#eedd78','#73a373','#73b9bc','#7289ab', '#91ca8c','#f49f42'], ... }, { type: 'pie', // 此系列自己的调色盘。 color: ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C','#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'], ... }] }
直接的样式设置 itemStyle,lineStyle,areaStyle,label……
高亮的样式:emphasis
默认情况下,高亮的样式是根据普通样式自动生成的。也可以通过 emphasis 属性定制。
option = { series: { type: 'scatter', // 普通样式。 itemStyle: { // 点的颜色。 color: 'red' }, label: { show: true, // 标签的文字。 formatter: 'This is a normal label.' }, // 高亮样式。 emphasis: { itemStyle: { // 高亮时点的颜色。 color: 'blue' }, label: { show: true, // 高亮时标签的文字。 formatter: 'This is a emphasis label.' } } } }
在 ECharts4 以前,高亮和普通样式的写法是这样的:
option = { series: { type: 'scatter', itemStyle: { // 普通样式。 normal: { // 点的颜色。 color: 'red' }, // 高亮样式。 emphasis: { // 高亮时点的颜色。 color: 'blue' } }, label: { // 普通样式。 normal: { show: true, // 标签的文字。 formatter: 'This is a normal label.' }, // 高亮样式。 emphasis: { show: true, // 高亮时标签的文字。 formatter: 'This is a emphasis label.' } } } }
这种写法依然兼容,但不推荐。
通过 visualMap 组件设定样式
visualMap 组件能指定数据到颜色、图形尺寸的映射规则,详见 数据的视觉映射
异步数据加载和更新
异步加载
可以获取数据后再通过 setOption
填入数据和配置项。或者先设置其他的样式,显示一个空的直角坐标轴,然后获取数据后填入数据。
var myChart = echarts.init(document.getElementById('main')); // 显示标题,图例和空的坐标轴 myChart.setOption({ title: { text: '异步数据加载示例' }, tooltip: {}, legend: { data:['销量'] }, xAxis: { data: [] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [] }] }); // 异步加载数据 $.get('data.json').done(function (data) { // 填入数据 myChart.setOption({ xAxis: { data: data.categories }, series: [{ // 根据名字对应到相应的系列 name: '销量', data: data.data }] }); });
虽然更新时 name
属性可以不存在,但还是推荐加上系列的 name
数据。
loading 动画
ECharts 默认提供了一个简单的加载动画。只需要调用 showLoading 方法显示。数据加载完成后在调用 hideLoading 方法隐藏加载动画。
myChart.showLoading(); $.get('data.json').done(function (data) { myChart.hideLoading(); myChart.setOption(...); });
数据的动态更新
所有数据的更新都通过 setOption实现,你只需要定时获取数据,setOption 填入数据,而不用考虑数据到底产生了那些变化,ECharts 会找到两组数据之间的差异然后通过合适的动画去表现数据的变化。
使用 dataset 管理数据
ECharts 4 开始支持了 dataset 组件用于单独的数据集声明,从而数据可以单独管理,被多个组件复用,并且可以基于数据指定数据到视觉的映射。他带来了这些效果:
- 能够贴近这样的数据可视化常见思维方式:基于数据(dataset 组件来提供数据),指定数据到视觉的映射(由 encode 属性来指定映射),形成图表。
- 数据和其他配置可以被分离开来,使用者相对便于进行单独管理,也省去了一些数据处理的步骤。
- 数据可以被多个系列或者组件复用,对于大数据,不必为每个系列创建一份。
- 支持更多的数据的常用格式,例如二维数组、对象数组等,一定程度上避免使用者为了数据格式而进行转换。
入门例子
option = { legend: {}, tooltip: {}, dataset: { // 提供一份数据。 source: [ ['product', '2015', '2016', '2017'], ['Matcha Latte', 43.3, 85.8, 93.7], ['Milk Tea', 83.1, 73.4, 55.1], ['Cheese Cocoa', 86.4, 65.2, 82.5], ['Walnut Brownie', 72.4, 53.9, 39.1] ] }, // 声明一个 X 轴,类目轴(category)。默认情况下,类目轴对应到 dataset 第一列。 xAxis: {type: 'category'}, // 声明一个 Y 轴,数值轴。 yAxis: {}, // 声明多个 bar 系列,默认情况下,每个系列会自动对应到 dataset 的每一列。 series: [ {type: 'bar'}, {type: 'bar'}, {type: 'bar'} ] }
或者也可以使用常见的对象数据的格式:
option = { legend: {}, tooltip: {}, dataset: { // 这里指定了维度名的顺序,从而可以利用默认的维度到坐标轴的映射。 // 如果不指定 dimensions,也可以通过指定 series.encode 完成映射,参见后文。 dimensions: ['product', '2015', '2016', '2017'], source: [ {product: 'Matcha Latte', '2015': 43.3, '2016': 85.8, '2017': 93.7}, {product: 'Milk Tea', '2015': 83.1, '2016': 73.4, '2017': 55.1}, {product: 'Cheese Cocoa', '2015': 86.4, '2016': 65.2, '2017': 82.5}, {product: 'Walnut Brownie', '2015': 72.4, '2016': 53.9, '2017': 39.1} ] }, xAxis: {type: 'category'}, yAxis: {}, series: [ {type: 'bar'}, {type: 'bar'}, {type: 'bar'} ] };
数据到图形的映射
本篇里,我们制作数据可视化图表的逻辑是这样的:基于数据,在配置项中指定如何映射到图形。
概略而言,可以进行这些映射:
- 指定 dataset 的列(column)还是行(row)映射为图形系列(series)。这件事可以使用 series.seriesLayoutBy 属性来配置。默认是按照列(column)来映射。
- 指定维度映射的规则:如何从 dataset 的维度(一个“维度”的意思是一行/列)映射到坐标轴(如 X、Y 轴)、提示框(tooltip)、标签(label)、图形元素大小颜色等(visualMap)。这件事可以使用 series.encode 属性,以及 visualMap 组件(如果有需要映射颜色大小等视觉维度的话)来配置。上面的例子中,没有给出这种映射配置,那么 ECharts 就按最常见的理解进行默认映射:X 坐标轴声明为类目轴,默认情况下会自动对应到 dataset.source 中的第一列;三个柱图系列,一一对应到 dataset.source 中后面每一列。
按行还是按列做映射
用户可以使用 seriesLayoutBy
配置项,改变图表对于行列的理解。seriesLayoutBy
可取值:
- ‘column’: 默认值。系列被安放到 dataset 的列上面。
- ‘row’: 系列被安放到 dataset 的行上面。
option = { legend: {}, tooltip: {}, dataset: { source: [ ['product', '2012', '2013', '2014', '2015'], ['Matcha Latte', 41.1, 30.4, 65.1, 53.3], ['Milk Tea', 86.5, 92.1, 85.7, 83.1], ['Cheese Cocoa', 24.1, 67.2, 79.5, 86.4] ] }, xAxis: [ {type: 'category', gridIndex: 0}, {type: 'category', gridIndex: 1} ], yAxis: [ {gridIndex: 0}, {gridIndex: 1} ], grid: [ {bottom: '55%'}, {top: '55%'} ], series: [ // 这几个系列会在第一个直角坐标系中,每个系列对应到 dataset 的每一行。 {type: 'bar', seriesLayoutBy: 'row'}, {type: 'bar', seriesLayoutBy: 'row'}, {type: 'bar', seriesLayoutBy: 'row'}, // 这几个系列会在第二个直角坐标系中,每个系列对应到 dataset 的每一列。 {type: 'bar', xAxisIndex: 1, yAxisIndex: 1}, {type: 'bar', xAxisIndex: 1, yAxisIndex: 1}, {type: 'bar', xAxisIndex: 1, yAxisIndex: 1}, {type: 'bar', xAxisIndex: 1, yAxisIndex: 1} ] }
纬度
常用图表所描述的数据大部分是“二维表”结构,上述的例子中,我们都使用二维数组来容纳二维表。现在,当我们把系列(series)对应到“列”的时候,那么每一列就称为一个“维度(dimension)”,而每一行称为数据项(item)。反之,如果我们把系列(series)对应到表行,那么每一行就是“维度(dimension)”,每一列就是数据项(item)。
维度可以有单独的名字,便于在图表中显示。维度名(dimension name)可以在定义在 dataset 的第一行(或者第一列)。例如下面的例子中,’score’、’amount’、’product’ 就是维度名。从第二行开始,才是正式的数据。dataset.source 中第一行(列)到底包含不包含维度名,ECharts 默认会自动探测。当然也可以设置 dataset.sourceHeader: true 显示声明第一行(列)就是维度,或者 dataset.sourceHeader: false 表明第一行(列)开始就直接是数据。
维度的定义,也可以使用单独的 dataset.dimensions 或者 series.dimensions 来定义,这样可以同时指定维度名,和维度的类型(dimension type):
var option1 = { dataset: { dimensions: [ {name: 'score'}, // 可以简写为 string,表示维度名。 'amount', // 可以在 type 中指定维度类型。 {name: 'product', type: 'ordinal'} ], source: [...] }, ... }; var option2 = { dataset: { source: [...] }, series: { type: 'line', // 在系列中设置的 dimensions 会更优先采纳。 dimensions: [ null, // 可以设置为 null 表示不想设置维度名 'amount', {name: 'product', type: 'ordinal'} ] }, ... };
大多数情况下,我们并不需要去设置维度类型,因为会自动判断。但是如果因为数据为空之类原因导致判断不足够准确时,可以手动设置维度类型。
维度类型(dimension type)可以取这些值:
- ‘number’: 默认,表示普通数据。
- ‘ordinal’: 对于类目、文本这些 string 类型的数据,如果需要能在数轴上使用,须是 ‘ordinal’ 类型。ECharts 默认会自动判断这个类型。但是自动判断也是不可能很完备的,所以使用者也可以手动强制指定。
- ‘time’: 表示时间数据。设置成 ‘time’ 则能支持自动解析数据成时间戳(timestamp),比如该维度的数据是 ‘2017-05-10’,会自动被解析。如果这个维度被用在时间数轴(axis.type 为 ‘time’)上,那么会被自动设置为 ‘time’ 类型。时间类型的支持参见 data。
- ‘float’: 如果设置成 ‘float’,在存储时候会使用 TypedArray,对性能优化有好处。
- ‘int’: 如果设置成 ‘int’,在存储时候会使用 TypedArray,对性能优化有好处。
数据到图形的映射(encode)
了解了纬度的概念后,我们就可以使用 encode 来做映射。
var option = { dataset: { source: [ ['score', 'amount', 'product'], [89.3, 58212, 'Matcha Latte'], [57.1, 78254, 'Milk Tea'], [74.4, 41032, 'Cheese Cocoa'], [50.1, 12755, 'Cheese Brownie'], [89.7, 20145, 'Matcha Cocoa'], [68.1, 79146, 'Tea'], [19.6, 91852, 'Orange Juice'], [10.6, 101852, 'Lemon Juice'], [32.7, 20112, 'Walnut Brownie'] ] }, xAxis: {}, yAxis: {type: 'category'}, series: [ { type: 'bar', encode: { // 将 "amount" 列映射到 X 轴。 x: 'amount', // 将 "product" 列映射到 Y 轴。 y: 'product' } } ] };
encode 声明的基本结构如下,其中冒号左边是坐标系、标签等特定名称,如 ‘x’, ‘y’, ‘tooltip’ 等,冒号右边是数据中的维度名(string 格式)或者维度的序号(number 格式,从 0 开始计数),可以指定一个或多个维度(使用数组)。通常情况下,下面各种信息不需要所有的都写,按需写即可。
// 例如在直角坐标系(grid/cartesian)中: encode: { // 把 “维度1”、“维度5”、“名为 score 的维度” 映射到 X 轴: x: [1, 5, 'score'], // 把“维度0”映射到 Y 轴。 y: 0, // 使用 “名为 product 的维度” 和 “名为 score 的维度” 的值在 tooltip 中显示 tooltip: ['product', 'score'] // 使用 “维度 3” 的维度名作为系列名。(有时候名字比较长,这可以避免在 series.name 重复输入这些名字) seriesName: 3, // 表示使用 “维度2” 中的值作为 id。这在使用 setOption 动态更新数据时有用处,可以使新老数据用 id 对应起来,从而能够产生合适的数据更新动画。 itemId: 2, // 指定数据项的名称使用 “维度3” 在饼图等图表中有用,可以使这个名字显示在图例(legend)中。 itemName: 3 } // 对于极坐标系,可以是: encode: { radius: 3, angle: 2, ... } // 对于地理坐标系,可以是: encode: { lng: 3, lat: 2 } // 对于一些没有坐标系的图表,例如饼图、漏斗图等,可以是: encode: { value: 3 }
视觉通道(颜色、尺寸等)的映射
我们可以使用 visualMap 组件进行视觉通道的映射。详见 visualMap 文档的介绍。
默认的映射
指的一提的是,ECharts 针对最常见直角坐标系中的图表(折线图、柱状图、散点图、K线图等)、饼图、漏斗图,给出了简单的默认的映射,从而不需要配置 encode 也可以出现图表(一旦给出了 encode,那么就不会采用默认映射)。默认的映射规则不易做得复杂,基本规则大体是:
- 在坐标系中(如直角坐标系、极坐标系等)
- 如果有类目轴(axis.type 为 ‘category’),则将第一列(行)映射到这个轴上,后续每一列(行)对应一个系列。
- 如果没有类目轴,假如坐标系有两个轴(例如直角坐标系的 X Y 轴),则每两列对应一个系列,这两列分别映射到这两个轴上。
- 如果没有坐标系(如饼图)
- 取第一列(行)为名字,第二列(行)为数值(如果只有一列,则取第一列为数值)。
几个常见的映射方式
数据的各种格式
常见的数据表格软件可以导出为 JSON 格式以供使用。
除了二维数组以外,dataset 也支持例如下面 key-value 方式的数据格式,这类格式也非常常见。但是这类格式中,目前并不支持 seriesLayoutBy 参数。
dataset: [{ // 按行的 key-value 形式(对象数组),这是个比较常见的格式。 source: [ {product: 'Matcha Latte', count: 823, score: 95.8}, {product: 'Milk Tea', count: 235, score: 81.4}, {product: 'Cheese Cocoa', count: 1042, score: 91.2}, {product: 'Walnut Brownie', count: 988, score: 76.9} ] }, { // 按列的 key-value 形式。 source: { 'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'], 'count': [823, 235, 1042, 988], 'score': [95.8, 81.4, 91.2, 76.9] } }]
多个 dataset 和他们的引用
可以同时定义多个 dataset。系列可以通过 series.datasetIndex 来指定引用哪个 dataset。例如:
var option = { dataset: [{ // 序号为 0 的 dataset。 source: [...], }, { // 序号为 1 的 dataset。 source: [...] }, { // 序号为 2 的 dataset。 source: [...] }], series: [{ // 使用序号为 2 的 dataset。 datasetIndex: 2 }, { // 使用序号为 1 的 dataset。 datasetIndex: 1 }] }
ECharts 3 的数据设置方式(series.data)仍正常使用
ECharts 4 之前一直以来的数据声明方式仍然被正常支持,如果系列已经声明了 series.data, 那么就会使用 series.data 而非 dataset。
{ xAxis: { type: 'category' data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'] }, yAxis: {}, series: [{ type: 'bar', name: '2015', data: [89.3, 92.1, 94.4, 85.4] }, { type: 'bar', name: '2016', data: [95.8, 89.4, 91.2, 76.9] }, { type: 'bar', name: '2017', data: [97.7, 83.1, 92.5, 78.1] }] }
其实,series.data 也是种会一直存在的重要设置方式。一些特殊的非 table 格式的图表,如 treemap、graph、lines 等,现在仍不支持在 dataset 中设置,仍然需要使用 series.data。另外,对于巨大数据量的渲染(如百万以上的数据量),需要使用 appendData 进行增量加载,这种情况不支持使用 dataset。
其他
目前并非所有图表都支持 dataset。支持 dataset 的图表有: line、bar、pie、scatter、effectScatter、parallel、candlestick、map、funnel、custom。 后续会有更多的图表进行支持。
在图表中加入交互组件
除了图表外 ECharts 中,提供了很多交互组件。例如:
图例组件 legend、标题组件 title、视觉映射组件 visualMap、数据区域缩放组件 dataZoom、时间线组件 timeline
数据区域缩放组件(dataZoom)介绍
『概览数据整体,按需关注数据细节』是数据可视化的基本交互需求。dataZoom 组件能够在直角坐标系(grid)、极坐标系(polar)中实现这一功能。
- dataZoom 组件是对 数轴(axis) 进行『数据窗口缩放』『数据窗口平移』操作。
可以通过 dataZoom.xAxisIndex 或 dataZoom.yAxisIndex 来指定 dataZoom 控制哪个或哪些数轴。
dataZoom 组件可同时存在多个,起到共同控制的作用。控制同一个数轴的组件,会自动联动。下面例子中会详细说明。
- dataZoom 的运行原理是通过『数据过滤』来达到『数据窗口缩放』的效果。
数据过滤模式的设置不同,效果也不同,参见:dataZoom.filterMode。
- dataZoom 的数据窗口范围的设置,目前支持两种形式:
- 百分比形式:参见 dataZoom.start 和 dataZoom.end。
- 绝对数值形式:参见 dataZoom.startValue 和 dataZoom.endValue。
dataZoom 组件现在支持几种子组件
- 内置型数据区域缩放组件(dataZoomInside):内置于坐标系中。
- 滑动条型数据区域缩放组件(dataZoomSlider):有单独的滑动条操作。
- 框选型数据区域缩放组件(dataZoomSelect):全屏的选框进行数据区域缩放。入口和配置项均在 toolbox中。
在代码加入 dataZoom 组件
<body> <div id="main"></div> <script> let myChart = echarts.init(document.getElementById('main')); let option = { xAxis: { type: 'value' }, yAxis: { type: 'value' }, dataZoom: [ { type: 'slider', xAxisIndex: 0, start: 10, end: 60 }, { type: 'inside', xAxisIndex: 0, start: 10, end: 60 }, { type: 'slider', yAxisIndex: 0, start: 30, end: 80 }, { type: 'inside', yAxisIndex: 0, start: 30, end: 80 } ], series: [ { type: 'scatter', itemStyle: { opacity: .8 }, symbolSize: function(val){ return val[2] * 40; }, data: [ ["14.616","7.241","0.896"], ["3.958","5.701","0.955"], ["2.768","8.971","0.669"], ["9.051","9.710","0.171"], ["14.046","4.182","0.536"], ["12.295","1.429","0.962"], ["4.417","8.167","0.113"], ["0.492","4.771","0.785"], ["7.632","2.605","0.645"], ["14.242","5.042","0.368"] ] } ] }; myChart.setOption(option); </script> </body>
移动端自适应
为了让 ECharts 内部组件随着容器尺寸变化而变化,ECharts 完善了组件的定位设置,并且实现了类似 CSS Media Query 的自适应能力。
ECharts 组件的定位和布局
大部分『组件』和『系列』会遵循两种定位方式:
left/right/top/bottom/width/height 定位方式:
这六个量中,每个量都可以是『绝对值』或者『百分比』或者『位置描述』。
center / radius 定位方式:
- center
是一个数组,表示 [x, y],其中,x、y可以是『绝对值』或者『百分比』.
- radius
是一个数组,表示 [内半径, 外半径],其中,内外半径可以是『绝对值』或者『百分比』.
横向(horizontal)和纵向(vertical)
- ECharts的『外观狭长』型的组件(如 legend、visualMap、dataZoom、timeline等),大多提供了『横向布局』『纵向布局』的选择。例如,在细长的移动端屏幕上,可能适合使用『纵向布局』;在PC宽屏上,可能适合使用『横向布局』。
- 横纵向布局的设置,一般在『组件』或者『系列』的 orient 或者 layout 配置项上,设置为 ‘horizontal’ 或者 ‘vertical’。
Media Query
Media Query 提供了【随着容器尺寸改变而改变】的能力。要在 option 中设置 Media Query 须遵循如下格式:
option = { baseOption: { // 这里是基本的『原子option』。 title: {...}, legend: {...}, series: [{...}, {...}, ...], ... }, media: [ // 这里定义了 media query 的逐条规则。 { query: {...}, // 这里写规则。 option: { // 这里写此规则满足下的option。 legend: {...}, ... } }, { query: {...}, // 第二个规则。 option: { // 第二个规则对应的option。 legend: {...}, ... } }, { // 这条里没有写规则,表示『默认』, option: { // 即所有规则都不满足时,采纳这个option。 legend: {...}, ... } } ] };
上面的例子中,baseOption、以及 media 每个 option 都是『原子 option』,即普通的含有各组件、系列定义的 option。而由『原子option』组合成的整个 option,我们称为『复合 option』。baseOption 是必然被使用的,此外,满足了某个 query 条件时,对应的 option 会被使用 chart.mergeOption() 来 merge 进去。
query:
每个 query 类似于这样:
{ minWidth: 200, maxHeight: 300, minAspectRatio: 1.3 }
现在支持三个属性:width、height、aspectRatio(长宽比)。每个属性都可以加上 min 或 max 前缀。比如,minWidth: 200 表示『大于等于200px宽度』。两个属性一起写表示『并且』,比如:{minWidth: 200, maxHeight: 300} 表示『大于等于200px宽度,并且小于等于300px高度』。
option:
media中的 option 既然是『原子 option』,理论上可以写任何 option 的配置项。但是一般我们只写跟布局定位相关的,例如截取上面例子中的一部分 query option:
media: [ ..., { query: { maxAspectRatio: 1 // 当长宽比小于1时。 }, option: { legend: { // legend 放在底部中间。 right: 'center', bottom: 0, orient: 'horizontal' // legend 横向布局。 }, series: [ // 两个饼图左右布局。 { radius: [20, '50%'], center: ['50%', '30%'] }, { radius: [30, '50%'], center: ['50%', '70%'] } ] } }, { query: { maxWidth: 500 // 当容器宽度小于 500 时。 }, option: { legend: { right: 10, // legend 放置在右侧中间。 top: '15%', orient: 'vertical' // 纵向布局。 }, series: [ // 两个饼图上下布局。 { radius: [20, '50%'], center: ['50%', '30%'] }, { radius: [30, '50%'], center: ['50%', '75%'] } ] } }, ... ]
多个 query 被满足时的优先级:
定义在后的后被 merge(即优先级更高)。
默认 query:
如果 media 中有某项不写 query,则表示『默认值』,即所有规则都不满足时,采纳这个option。
容器大小实时变化时的注意事项:
在不少情况下,并不需要容器DOM节点任意随着拖拽变化大小,而是只是根据不同终端设置几个典型尺寸。
但是如果容器DOM节点需要能任意随着拖拽变化大小,那么目前使用时需要注意这件事:某个配置项,如果在某一个 query option 中出现,那么在其他 query option 中也必须出现,否则不能够回归到原来的状态。(left/right/top/bottom/width/height 不受这个限制。)
『复合 option』 中的 media 不支持 merge
也就是说,当第二(或三、四、五 …)次 chart.setOption(rawOption) 时,如果 rawOption 是 复合option(即包含 media 列表),那么新的 rawOption.media 列表不会和老的 media 列表进行 merge,而是简单替代。当然,rawOption.baseOption 仍然会正常和老的 option 进行merge。
其实,很少有场景需要使用『复合 option』来多次 setOption,而我们推荐的做法是,使用 mediaQuery 时,第一次setOption使用『复合 option』,后面 setOption 时仅使用 『原子 option』,也就是仅仅用 setOption 来改变 baseOption。
数据的视觉映射
数据可视化是 数据 到 视觉元素 的映射过程(这个过程也可称为视觉编码,视觉元素也可称为视觉通道)。
ECharts 的每种图表本身就内置了这种映射过程,比如折线图把数据映射到『线』,柱状图把数据映射到『长度』。一些更复杂的图表,如 graph、事件河流图、treemap 也都会做出他们内置的映射。
此外,ECharts 还提供了 visualMap 组件 来提供通用的视觉映射。visualMap 组件中可以使用的视觉元素有:
图形类别(symbol)、图形大小(symbolSize)
颜色(color)、透明度(opacity)、颜色透明度(colorAlpha)、
颜色明暗度(colorLightness)、颜色饱和度(colorSaturation)、色调(colorHue)
下面对 visualMap 组件的使用方式进行简要的介绍。
数据和维度
ECharts中的数据,一般存放于 series.data 中。根据图表类型不同,数据的具体形式也可能有些许差异。比如可能是『线性表』、『树』、『图』等。但他们都有个共性:都是『数据项(dataItem)』的集合。每个数据项含有『数据值(value)』和其他信息(如果需要的话)。每个数据值,可以是单一的数值(一维)或者一个数组(多维)。
在图表中,往往默认把 value 的前一两个维度进行映射,比如取第一个维度映射到x轴,取第二个维度映射到y轴。如果想要把更多的维度展现出来,可以借助 visualMap 。最常见的情况,气泡图(scatter) 使用半径展现了第三个维度。
visualMap 组件
visualMap 组件定义了把数据的『哪个维度』映射到『什么视觉元素上』。
现在提供如下两种类型的visualMap组件,通过 visualMap.type 来区分。
其定义结构例如:
option = { visualMap: [ // 可以同时定义多个 visualMap 组件。 { // 第一个 visualMap 组件 type: 'continuous', // 定义为连续型 viusalMap ... }, { // 第二个 visualMap 组件 type: 'piecewise', // 定义为分段型 visualMap ... } ], ... };
分段型视觉映射组件(visualMapPiecewise),有三种模式:
- 连续型数据平均分段: 依据 visualMap-piecewise.splitNumber 来自动平均分割成若干块。
- 连续型数据自定义分段: 依据 visualMap-piecewise.pieces 来定义每块范围。
- 离散数据(类别性数据): 类别定义在 visualMap-piecewise.categories 中。
视觉映射方式的配置
既然是『数据』到『视觉元素』的映射,visualMap 中可以指定数据的『哪个维度』(参见visualMap.dimension)映射到哪些『视觉元素』(参见 visualMap.inRange 和 visualMap.outOfRange)中。
option = { visualMap: [ { type: 'piecewise' min: 0, max: 5000, dimension: 3, // series.data 的第四个维度(即 value[3])被映射 seriesIndex: 4, // 对第四个系列进行映射。 inRange: { // 选中范围中的视觉配置 color: ['blue', '#121122', 'red'], // 定义了图形颜色映射的颜色列表, // 数据最小值映射到'blue'上, // 最大值映射到'red'上, // 其余自动线性计算。 symbolSize: [30, 100] // 定义了图形尺寸的映射范围, // 数据最小值映射到30上, // 最大值映射到100上, // 其余自动线性计算。 }, outOfRange: { // 选中范围外的视觉配置 symbolSize: [30, 100] } }, ... ] };
option = { visualMap: [ { ..., inRange: { // 选中范围中的视觉配置 colorLightness: [0.2, 1], // 映射到明暗度上。也就是对本来的颜色进行明暗度处理。 // 本来的颜色可能是从全局色板中选取的颜色,visualMap组件并不关心。 symbolSize: [30, 100] }, ... }, ... ] };
ECharts 中的事件和行为
在 ECharts 的图表中用户的操作将会触发相应的事件。在 ECharts 中事件分为两种类型,一种是用户鼠标操作点击,或者 hover 图表的图形时触发的事件,还有一种是用户在使用可以交互的组件后触发的行为事件,例如在切换图例开关时触发的 ‘legendselectchanged’ 事件(这里需要注意切换图例开关是不会触发’legendselected’事件的),数据区域缩放时触发的 ‘datazoom’ 事件等等。
鼠标事件的处理
ECharts 支持常规的鼠标事件类型,包括 ‘click’、’dblclick’、’mousedown’、’mousemove’、’mouseup’、’mouseover’、’mouseout’ 事件。下面先来看一个简单的点击柱状图后打开相应的百度搜索页面的示例。
// 基于准备好的dom,初始化ECharts实例 var myChart = echarts.init(document.getElementById('main')); // 指定图表的配置项和数据 var option = { xAxis: { data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"] }, yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); // 处理点击事件并且跳转到相应的百度搜索页面 myChart.on('click', function (params) { window.open('https://www.baidu.com/s?wd=' + encodeURIComponent(params.name)); });
组件交互的行为事件
在 ECharts 中基本上所有的组件交互行为都会触发相应的事件,常用的事件和事件对应参数在 events 文档中有列出。
下面是监听一个图例开关的示例:
// 图例开关的行为只会触发 legendselectchanged 事件 myChart.on('legendselectchanged', function (params) { // 获取点击图例的选中状态 var isSelected = params.selected[params.name]; // 在控制台中打印 console.log((isSelected ? '选中了' : '取消选中了') + '图例' + params.name); // 打印所有图例的状态 console.log(params.selected); });
代码触发 ECharts 中组件的行为
有时会需要在程序里调用方法触发图表的行为,比如显示 tooltip,选中图例。
在 ECharts 2.x 是通过 myChart.component.tooltip.showTip 这种形式调用相应的接口触发图表行为,入口很深,而且涉及到内部组件的组织。相对地,在 ECharts 3 里改为通过调用 myChart.dispatchAction({ type: ” }) 触发图表行为,统一管理了所有动作,也可以方便地根据需要去记录用户的行为路径。
常用的动作和动作对应参数在 action 文档中有列出。
小例子:自己实现拖拽
小例子:实现日历图
自定义配置参数
使用日历坐标绘制日历图时,支持自定义各项属性:
- range: 设置时间的范围,可支持某年、某月、某天,还可支持跨年
- cellSize: 设置日历格的大小,可支持设置不同高宽,还可支持自适应auto
- width、height: 也可以直接设置改日历图的整体高宽,让其基于已有的高宽全部自适应
- orient: 设置坐标的方向,既可以横着也可以竖着
- splitLine: 设置分隔线样式,也可以直接不显示
- itemStyle: 设置日历格的样式,背景色、方框线颜色大小类型、透明度均可自定义,甚至还能加阴影
- dayLabel: 设置坐标中 星期样式,可以设置星期从第几天开始,快捷设置中英文、甚至是自定义中英文混搭、或局部不显示、通过formatter 可以想怎么显示就怎么显示;
- monthLabel: 设置坐标中 月样式,和星期一样,可快捷设置中英文和自定义混搭
- yearLabel: 设置坐标中 年样式,默认显示一年,通过formatter 文字可以想显示什么就能通过string function任性自定义,上下左右方位随便选;
完整的配置项参数参见:calendar API
旭日图
旭日图(Sunburst)由多层的环形图组成,在数据结构上,内圈是外圈的父节点。因此,它既能像饼图一样表现局部和整体的占比,又能像矩形树图一样表现层级关系。
引入相关文件
旭日图是 ECharts4.0 新增的图表类型,需要下载完整版 EChartts 才可以使用。
最简单的旭日图
创建旭日图需要在 series 配置项中声明类型为 ‘sunburst’ 的系列,并且以树形结构声明其 data:
var option = { series: { type: 'sunburst', data: [{ name: 'A', value: 10, children: [{ value: 3, name: 'Aa' }, { value: 5, name: 'Ab' }] }, { name: 'B', children: [{ name: 'Ba', value: 4 }, { name: 'Bb', value: 2 }] }, { name: 'C', value: 3 }] } };
颜色等样式调整
默认情况下会使用全局调色盘 color 分配最内层的颜色,其余层则与其父元素同色。在旭日图中,扇形块的颜色有以下三种设置方式:
- 在 series.data.itemStyle 中设置每个扇形块的样式;
- 在 series.levels.itemStyle 中设置每一层的样式;
- 在 series.itemStyle 中设置整个旭日图的样式。
上述三者的优先级是从高到低的,也就是说,配置了 series.data.itemStyle 的扇形块将会覆盖 series.levels.itemStyle 和 series.itemStyle 的设置。
var option = { series: { type: 'sunburst', data: [{ name: 'A', value: 10, children: [{ value: 3, name: 'Aa', itemStyle: { color: 'red' } }, { value: 5, name: 'Ab' }] }, { name: 'B', children: [{ name: 'Ba', value: 4 }, { name: 'Bb', value: 2 }], itemStyle: { color: 'red' } }, { name: 'C', value: 3 }], itemStyle: { color: '#aaa' }, levels: [{ // 留给数据下钻的节点属性 }, { itemStyle: { color: 'blue' } }] } };
按层配置样式
旭日图是一种有层次的结构,为了方便同一层样式的配置,我们提供了 levels 配置项。它是一个数组,其中的第 0 项表示数据下钻后返回上级的图形,其后的每一项分别表示从圆心向外层的层级。
数据下钻
旭日图默认支持数据下钻,也就是说,当点击了扇形块之后,将以该扇形块的数据作为根节点,便于进一步了解该数据的细节。
当数据下钻后,中间会出现一个用于返回上一层的图形,该图形的样式可以通过 levels[0] 配置。
如果不需要数据下钻功能,可以通过将 nodeClick 设置为 false 关闭;或者将其设为 ‘link’,并将 data.link 设为点击扇形块对应打开的链接。
高亮相关扇形块
旭日图支持鼠标移动到某扇形块时,高亮相关数据块的操作,可以通过设置 highlightPolicy,包括以下几种高亮方式:
- ‘descendant’(默认值):高亮鼠标移动所在扇形块与其后代元素;
- ‘ancestor’:高亮鼠标所在扇形块与其祖先元素;
- ‘self’:仅高亮鼠标所在扇形块;
- ‘none’:不会淡化(downplay)其他元素。
上面提到的“高亮”,对于鼠标所在的扇形块,会使用 emphasis 样式;对于其他相关扇形块,则会使用 highlight 样式。通过这种方式,可以很方便地实现突出显示相关数据的需求。
具体来说,对于配置项:
itemStyle: { color: 'yellow', borderWidth: 2, emphasis: { color: 'red' }, highlight: { color: 'orange' }, downplay: { color: '#ccc' } }
总结
上面的教程主要讲述的是如何入门使用旭日图,感兴趣的用户可以在 配置项手册 查看更完整的文档。在灵活应用这些配置项之后,就能做出丰富多彩的旭日图了!
自定义系列
自定义系列(custom series),是一种系列的类型。它把绘制图形元素这一步留给开发者去做,从而开发者能在坐标系中自由绘制出自己需要的图表。
(一)renderItem 方法
开发者自定义的图形元素渲染逻辑,是通过书写 renderItem 函数实现的。在渲染阶段,对于 series.data 中的每个数据项(为方便描述,这里称为 dataItem),会调用此 renderItem 函数。这个 renderItem 函数的职责,就是返回一个(或者一组)图形元素定义,图形元素定义 中包括图形元素的类型、位置、尺寸、样式等。echarts 会根据这些 图形元素定义 来渲染出图形元素。如下的示意:
var option = { ..., series: [{ type: 'custom', renderItem: function (params, api) { // 对于 data 中的每个 dataItem,都会调用这个 renderItem 函数。 // (但是注意,并不一定是按照 data 的顺序调用) // 这里进行一些处理,例如,坐标转换。 // 这里使用 api.value(0) 取出当前 dataItem 中第一个维度的数值。 var categoryIndex = api.value(0); // 这里使用 api.coord(...) 将数值在当前坐标系中转换成为屏幕上的点的像素值。 var startPoint = api.coord([api.value(1), categoryIndex]); var endPoint = api.coord([api.value(2), categoryIndex]); // 这里使用 api.size(...) 获得 Y 轴上数值范围为 1 的一段所对应的像素长度。 var height = api.size([0, 1])[1] * 0.6; // 这里返回为这个 dataItem 构建的图形元素定义。 return { // 表示这个图形元素是矩形。还可以是 'circle', 'sector', 'polygon' 等等。 type: 'rect', // shape 属性描述了这个矩形的像素位置和大小。 // 其中特殊得用到了 echarts.graphic.clipRectByRect,意思是, // 如果矩形超出了当前坐标系的包围盒,则剪裁这个矩形。 shape: echarts.graphic.clipRectByRect({ // 矩形的位置和大小。 x: startPoint[0], y: startPoint[1] - height / 2, width: endPoint[0] - startPoint[0], height: height }, { // 当前坐标系的包围盒。 x: params.coordSys.x, y: params.coordSys.y, width: params.coordSys.width, height: params.coordSys.height }), // 用 api.style(...) 得到默认的样式设置。这个样式设置包含了 // option 中 itemStyle 的配置和视觉映射得到的颜色。 style: api.style() }; }, data: [ [12, 44, 55, 60], // 这是第一个 dataItem [53, 31, 21, 56], // 这是第二个 dataItem [71, 33, 10, 20], // 这是第三个 dataItem ... ] }] }
renderItem 函数提供了两个参数:
- params:包含了当前数据信息(如 seriesIndex、dataIndex 等等)和坐标系的信息(如坐标系包围盒的位置和尺寸)。
- api:是一些开发者可调用的方法集合(如 api.value()、api.coord())。
renderItem 函数须返回根据此 dataItem 绘制出的图形元素的定义信息,参见 renderItem.return。
一般来说,renderItem 函数的主要逻辑,是将 dataItem 里的值映射到坐标系上的图形元素。这一般需要用到 renderItem.arguments.api 中的两个函数:
- api.value(…),意思是取出 dataItem 中的数值。例如 api.value(0) 表示取出当前 dataItem 中第一个维度的数值。
- api.coord(…),意思是进行坐标转换计算。例如 var point = api.coord([api.value(0), api.value(1)]) 表示 dataItem 中的数值转换成坐标系上的点。
有时候还需要用到 api.size(…) 函数,表示得到坐标系上一段数值范围对应的长度。
返回值中样式的设置可以使用 api.style(…) 函数,他能得到 series.itemStyle 中定义的样式信息,以及视觉映射的样式信息。也可以用这种方式覆盖这些样式信息:api.style({fill: ‘green’, stroke: ‘yellow’})。
书写完 renderItem 方法后,自定义系列的 90% 工作就做完了。剩下的是一些精化工作。
(二)使坐标轴的范围自适应数据范围
在 直角坐标系(grid)、极坐标系(polar) 中都有坐标轴。坐标轴的刻度范围需要自适应当前显示出的数据的范围,否则绘制出的图形会超出去。所以,例如,在 直角坐标系(grid) 中,使用自定义系列的开发者,需要设定,data 中的哪些维度会对应到 x 轴上,哪些维度会对应到 y 轴上。这件事通过 encode 来设定。例如:
option = { series: [{ type: 'custom', renderItem: function () { ... }, encode: { // data 中『维度1』和『维度2』对应到 X 轴 x: [1, 2], // data 中『维度0』对应到 Y 轴 y: 0 }, data: [ // 维度0 维度1 维度2 维度3 [ 12, 44, 55, 60 ], // 这是第一个 dataItem [ 53, 31, 21, 56 ], // 这是第二个 dataItem [ 71, 33, 10, 20 ], // 这是第三个 dataItem ... ] }] };
(三)设定 tooltip
当然,使用 tooltip.formatter 可以任意定制 tooltip 中的内容。但是还有更简单的方法,通过encode 和 dimensions 来设定:
option = { series: [{ type: 'custom', renderItem: function () { ... }, encode: { x: [1, 2], y: 0, // 表示『维度2』和『维度3』要显示到 tooltip 中。 tooltip: [2, 3] }, // 表示给『维度2』和『维度3』分别取名为『年龄』和『满意度』,显示到 tooltip 中。 dimensions: [null, null, '年龄', '满意度'], data: [ // 维度0 维度1 维度2 维度3 [ 12, 44, 55, 60 ], // 这是第一个 dataItem [ 53, 31, 21, 56 ], // 这是第二个 dataItem [ 71, 33, 10, 20 ], // 这是第三个 dataItem ... ] }] };
(四)其他注意事项
(1)与 dataZoom 结合使用的时候,常常使用会设置 dataZoom.filterMode 为 ‘weakFilter’。这个设置的意思是:当 dataItem 部分超出坐标系边界的时候,dataItem 不会整体被过滤掉。例如:
option = { dataZoom: { xAxisIndex: 0, filterMode: 'weakFilter' }, series: [{ type: 'custom', renderItem: function () { ... }, encode: { // data 中『维度1』和『维度2』对应到 X 轴 x: [1, 2], y: 0 }, data: [ // 维度0 维度1 维度2 维度3 [ 12, 44, 55, 60 ], // 这是第一个 dataItem [ 53, 31, 21, 56 ], // 这是第二个 dataItem [ 71, 33, 10, 20 ], // 这是第三个 dataItem ... ] }] };
在这个例子中,『维度1』和『维度2』对应到 X 轴,dataZoom 组件控制 X 轴的缩放。假如在缩放的过程中,某个 dataItem 的『维度1』超出了 X 轴的范围,『维度2』还在 X 轴的范围中,那么只要设置 dataZoom.filterMode = ‘weakFilter’,这个 dataItem 就不会被过滤掉,从而还能够使用 renderItem 绘制图形(可以使用上面提到过的 echarts.graphic.clipRectByRect 把图形绘制成被坐标系剪裁过的样子)。参见上面提到过的例子:Profile
(2)另外,开发者如果使用到的话应注意,renderItem.arguments.params 中的 dataIndex 和 dataIndexInside 是有区别的:
- dataIndex 指的 dataItem 在原始数据中的 index。
- dataIndexInside 指的是 dataItem 在当前数据窗口(参见 dataZoom)中的 index。
renderItem.arguments.api 中使用的参数都是 dataIndexInside 而非 dataIndex,因为从 dataIndex 转换成 dataIndexInside 需要时间开销。
富文本标签
在许多地方(如图、轴的标签等)都可以使用富文本标签。
原先 echarts 中的文本标签,只能对整块统一进行样式设置,并且仅仅支持颜色和字体的设置,从而导致不易于制作表达能力更强的文字描述信息。
echarts v3.7 以后,支持了富文本标签,能够:
- 能够定制文本块整体的样式(如背景、边框、阴影等)、位置、旋转等。
- 能够对文本块中个别片段定义样式(如颜色、字体、高宽、背景、阴影等)、对齐方式等。
- 能够在文本中使用图片做小图标或者背景。
- 特定组合以上的规则,可以做出简单表格、分割线等效果。
文本样式相关的配置项
echarts 提供了丰富的文本标签配置项,包括:
- 字体基本样式设置:fontStyle、fontWeight、fontSize、fontFamily。
- 文字颜色:color。
- 文字描边:textBorderColor、textBorderWidth。
- 文字阴影:textShadowColor、textShadowBlur、textShadowOffsetX、textShadowOffsetY。
- 文本块或文本片段大小:lineHeight、width、height、padding。
- 文本块或文本片段的对齐:align、verticalAlign。
- 文本块或文本片段的边框、背景(颜色或图片):backgroundColor、borderColor、borderWidth、borderRadius。
- 文本块或文本片段的阴影:shadowColor、shadowBlur、shadowOffsetX、shadowOffsetY。
- 文本块的位置和旋转:position、distance、rotate。
可以在各处的 rich 属性中定义文本片段样式。例如 series-bar.label.rich
label: { // 在文本中,可以对部分文本采用 rich 中定义样式。 // 这里需要在文本中使用标记符号: // `{styleName|text content text content}` 标记样式名。 // 注意,换行仍是使用 '\n'。 formatter: [ '{a|这段文本采用样式a}', '{b|这段文本采用样式b}这段用默认样式{x|这段用样式x}' ].join('\n'), // 这里是文本块的样式设置: color: '#333', fontSize: 5, fontFamily: 'Arial', borderWidth: 3, backgroundColor: '#984455', padding: [3, 10, 10, 5], lineHeight: 20, // rich 里是文本片段的样式设置: rich: { a: { color: 'red', lineHeight: 10 }, b: { backgroundColor: { image: 'xxx/xxx.jpg' }, height: 40 }, x: { fontSize: 18, fontFamily: 'Microsoft YaHei', borderColor: '#449933', borderRadius: 4 }, ... } }
注意:如果不定义 rich,不能指定文字块的 width 和 height。
文本、文本框、文本片段的基本样式和装饰
每个文本可以设置基本的字体样式:fontStyle、fontWeight、fontSize、fontFamily。
可以设置文字的颜色 color 和边框的颜色 textBorderColor、textBorderWidth。
文本框可以设置边框和背景的样式:borderColor、borderWidth、backgroundColor、padding。
文本片段也可以设置边框和背景的样式:borderColor、borderWidth、backgroundColor、padding。
标签的位置
对于折线图、柱状图、散点图等,均可以使用 label 来设置标签。标签的相对于图形元素的位置,一般使用 label.position、label.distance 来配置。
注意:position 在不同的图中可取值有所不同。distance 并不是在每个图中都支持。详情请参见 option 文档。
标签的旋转
某些图中,为了能有足够长的空间来显示标签,需要对标签进行旋转。比如横向变纵向。
这种场景下,可以结合 align 和 verticalAlign 来调整标签位置。
注意,逻辑是,先使用 align 和 verticalAlign 定位,再旋转。
文本片段的排版和对齐
关于排版方式,每个文本片段,可以想象成 CSS 中的 inline-block,在文档流中按行放置。
只有 ‘\n’ 是换行符,能导致换行。
文本片段的 lineHeight 可直接在 rich 中指定,也可以在 rich 的父层级中统一指定而采用到 rich 的所有项中,如果都不指定,则取文本片段的边框盒尺寸(border box size)。
在一行的 lineHeight 被决定后,一行内,文本片段的竖直位置,由文本片段的 verticalAlign 来指定(这里和 CSS 中的规则稍有不同):
- ‘bottom’:文本片段的盒的底边贴住行底。
- ‘top’:文本片段的盒的顶边贴住行顶。
- ‘middle’:居行中。
文本块的宽度,可以直接由文本块的 width 指定,否则,由最长的行决定。宽度决定后,在一行中进行文本片段的放置。文本片段的 align 决定了文本片段在行中的水平位置:
- 首先,从左向右连续紧靠放置 align 为 ‘left’ 的文本片段盒。
- 然后,从右向左连续紧靠放置 align 为 ‘right’ 的文本片段盒。
- 最后,剩余的没处理的文本片段盒,紧贴着,在中间剩余的区域中居中放置。
关于文字在文本片段盒中的位置:
- 如果 align 为 ‘center’,则文字在文本片段盒中是居中的。
- 如果 align 为 ‘left’,则文字在文本片段盒中是居左的。
- 如果 align 为 ‘right’,则文字在文本片段盒中是居右的。
特殊效果:图标、分割线、标题块、简单表格
文本片段的 backgroundColor 可以指定为图片后,就可以在文本中使用图标了:
rich: { Sunny: { // 这样设定 backgroundColor 就可以是图片了。 backgroundColor: { image: './data/asset/img/weather/sunny_128.png' }, // 可以只指定图片的高度,从而图片的宽度根据图片的长宽比自动得到。 height: 30 } }
分割线实际是用 border 实现的:
rich: { hr: { borderColor: '#777', // 这里把 width 设置为 '100%',表示分割线的长度充满文本块。 // 注意,这里是文本块内容盒(content box)的 100%,而不包含 padding。 // 虽然这和 CSS 相关的定义有所不同,但是在这类场景中更加方便。 width: '100%', borderWidth: 0.5, height: 0 } }
标题块是使用 backgroundColor 实现的:
// 标题文字居左 formatter: '{titleBg|Left Title}', rich: { titleBg: { backgroundColor: '#000', height: 30, borderRadius: [5, 5, 0, 0], padding: [0, 10, 0, 10], width: '100%', color: '#eee' } } // 标题文字居中。 // 这个实现有些 tricky,但是,能够不引入更复杂的排版规则而实现这个效果。 formatter: '{tc|Center Title}{titleBg|}', rich: { titleBg: { align: 'right', backgroundColor: '#000', height: 30, borderRadius: [5, 5, 0, 0], padding: [0, 10, 0, 10], width: '100%', color: '#eee' } }
使用 canvas 或者 svg 渲染
ECharts 从初始一直使用 Canvas 绘制图表(除了对 IE8- 使用 VML)。而 ECharts v4.0 发布了 SVG 渲染器,从而提供了一种新的选择。只须在初始化一个图表实例时,设置 renderer 参数 为 ‘canvas’ 或 ‘svg’ 即可指定渲染器,比较方便。
选择哪种渲染器
选择哪种渲染器,我们可以根据软硬件环境、数据量、功能需求综合考虑。
- 在软硬件环境较好,数据量不大的场景下(例如 PC 端做商务报表),两种渲染器都可以适用,并不需要太多纠结。
- 在环境较差,出现性能问题需要优化的场景下,可以通过试验来确定使用哪种渲染器。比如有这些经验:
- 在须要创建很多 ECharts 实例且浏览器易崩溃的情况下(可能是因为 Canvas 数量多导致内存占用超出手机承受能力),可以使用 SVG 渲染器来进行改善。大略得说,如果图表运行在低端安卓机,或者我们在使用一些特定图表如 水球图 等,SVG 渲染器可能效果更好。
- 数据量很大、较多交互时,可以选用 Canvas 渲染器。
注:除了某些特殊的渲染可能依赖 Canvas:如炫光尾迹特效、带有混合效果的热力图等,绝大部分功能 SVG 都是支持的。此外,目前的 SVG 版中,富文本、材质功能尚未实现。
如何使用渲染器
ECharts 默认使用 Canvas 渲染。如果想使用 SVG 渲染,ECharts 代码中须包括有 SVG 渲染器模块。
- ECharts 的 预构建文件 中,常用版 和 完整版 已经包含了 SVG 渲染器,可直接使用。而 精简版 没有包括。
- 如果 在线自定义构建 ECharts,则需要勾上页面下方的 “SVG 渲染”。
- 如果 线下自定义构建 ECharts,则须引入 SVG 渲染器模块,即:
import 'zrender/lib/svg/svg';
然后,我们就可以在代码中,初始化图表实例时,传入参数 选择渲染器类型:
// 使用 Canvas 渲染器(默认) var chart = echarts.init(containerDom, null, {renderer: 'canvas'}); // 等价于: var chart = echarts.init(containerDom); // 使用 SVG 渲染器 var chart = echarts.init(containerDom, null, {renderer: 'svg'});