您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

ECharts 事件系统

当我们的图表变得越来越庞大之后,我们加入的组件也会越来越多,所以我们之后做的不单单只有 “看”这动作,还要有其他的动作,对应的就是个事件的处理,操作触发事件,我们则可以通过监听事件并处理来完成一系列的事件操作,所以这一节我们就来从事件三要素事件绑定事件解绑这几个方面去了解一下 ECharts 的事件系统。

在 ECharts 的图表中的操作将会触发相应的事件。开发者可以监听这些事件,然后通过回调做相应的处理,比如到地址,或者弹出对话框,或者做数据下钻等等。更多细节可参考 。

解释

ECharts 开放了两套 API 体系,一是 ECharts 及,例如常用的 echarts.initechartInstance.setOption();二是围绕事件展开的动态交互接口,用于监听事件的 echartInstance.on 和用于触发行为的 echartInstance.dispatchAction

本文讨论使用 echartInstance.on 接口实现的事件监听。

与 类似,ECharts 通过事件、事件源、事件参数三个要素精确描述何处执行了何种操作。在展开示例讨论前,有必要简单讨论下 ECharts 事件三要素的含义。

ECharts 中存在两种类型的事件,第一种是鼠标在图形示例上的行为所触发的鼠标事件,:

上述事件除 globalout 外,均与 定义的同名事件有相同的语义、触发条件。globalout 在鼠标移出图表示例范围时触发。

第二种称为行为事件,在组件、图表状态发生某种业务状态迁移时触发,:

上表只摘录行为事件的关键部分,更详细的介绍请参考 。

行为事件的发生代表着组件实体内部状态发生了某些变更,有两种原因可能触发行为事件:

事件源描述了触发事件的主体,对于鼠标事件,事件源通常是行为发生时鼠标焦点所在图形区域对应的图表。所有类型的图表都鼠标事件;部分组件触发鼠标事件,但认是的,需要通过设置 triggerEvent: true 来启动。组件对鼠标事件的情况如下:

Tips:

graphic 是原生图形组件,echartInstance.on 接口,但可直接 等接口实现事件监听。

行为事件由特定的组件、图表触发,例如 legendselectchanged 的事件源只能是 legend 组件,更多信息请参考 一节。

事件参数描述事件发生时的上下文信息,ECharts中不同事件的参数信息相差极大,甚至同种事件在不同组件触发时,回调参数也有差异。

ECharts 鼠标事件,虽然上与 一致,但回调中传递的参数比标准相差很大。以 click 为例,DOM 的 click 事件参数是 对象,主要有:

{
	isTrusted: boolean,
	screenX: number,
	screenY: number,
	clientX: number,
	clientY: number,
	ctrlKey: boolean,
	shiftKey: boolean,
	altKey: boolean,
	Key: boolean,
	: object,
	pageX: number,
	pageY: number,
	x: number,
	y: number,
	offsetX: number,
  offsetY: number,
  ...
}

可以看出 DOM 的 click 事件参数详细描述了点击行为发生的位置、事件源的 dom、是否带有快捷键、捕获的阶段等。而 ECharts 在 series 上发生的 click 事件带有如下参数:

{
	// 当前点击的图形元素所属的组件,
	// 其值如 'series'、'markLine'、'markPoint'、'timeLine' 等。
	componentType: string,
	// 图形元素所属二级组件类型
	// 如 `bar`、`line`、`pie` 等
	componentSubType: string,
	componentIndex: number,
	// 系列类型。值可能为:'line'、'bar'、'pie' 等
	seriesType: string,
	// 系列在传入的 option.series 中的 index
	seriesIndex: number,
	// 系列ID
	seriesId: string,
	// 系列
	seriesName: string,
	// 数据名,类目名
	name: string,
	// 触发事件的数据在data数组中的index
	dataIndex: number,
	// 触发事件的数据所传入的原始data值
	data: number,
	// sankey、graph 等图表同时含有 nodeData 和 edgeData 两种 data,
	// dataType 的值会是 'node' 或者 'edge',表示当前点击在 node 还是 edge 上。
	// 其他大部分图表中只有一种 data,dataType 无意义。
	dataType: string,
	// 传入的数据值
	value: number | Array,
	// 数据图形的颜色
	color: string,
	// 数据图形的边框色
	borderColor: undefined,
	// 数据图形的维度信息
	dimensionNames: object,
	encode: object,
	// 信息的html
	marker: string,
	$vars: object,
	// 原始click事件参数
	event: object,
	// 事件,本例中为 `click`
	type: string,
}

可以看出,ECharts 传递的 click 事件参数侧重于描述发生点击行为的图形所对应的组件信息、状态、配置,比如上例中的 componentType、componentSubType 指明单击的组件类别、子类别;seriesType、seriesIndex、data 等指明单击组件所对应的数据配置值;marker、encode 则指明单击发生时,组件内部状态信息。大多数情况下这些信息是足够使用的,必要时也可以通过 event 读取原始 dom 事件参数。

需要注意的第二点是,即使是同种事件,不同组件所暴露的参数也是不一样的,以 click 为例,在 series.bar 上触发时有如下:

componentTypecomponentSubTypecomponentIndexseriesTypeseriesIndexseriesIdseriesNamenamedataIndexdatadataTypevaluecolorborderColordimensionNamesencodemarker$varseventtype

yAxis 则有:

componentTypecomponentIndexyAxisIndextargetTypevalueeventtype

title 上则是:

componentTypecomponentIndexeventtype

Tips
遗憾的是,官网并未就此给出详细、完整的列表,建议开发时通过 console.logdebugger 等手段各种组件所传递的事件参数。

与鼠标事件参数一样,行为事件也没有提供一致的参数模型,不过官网提供了 ,开发时建议前往查阅。

ECharts 中可通过 绑定事件处理,on 签名:

(eventName: string, query?: string|Object, handler: Function, context?: Object)

各参数说明:

若未提供 query 参数,ECharts 将不对事件源做任何过滤,相当于了全局事件回调。例如:

<!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">
			const myChart = echarts.init(document.getElementById('main'));

			const option = {
				title: {
					text: 'test',
					// 通过 triggerEvent 显式声明
					// 该组件将触发事件回调
					triggerEvent: true,
				},
				xAxis: {
					type: 'category',
					data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
					triggerEvent: true,
				},
				yAxis: {
					type: 'value',
					triggerEvent: true,
				},
				series: [
					{
						data: [, , , , , , ],
						type: 'bar',
					},
				],
			};
			myChart.setOption(option);

			//  `click` 事件回调
			myChart.on('click', function (e) {
				console.log(`click invoke at ${e.componentType}`);
			});
		</script>
	</body>
</html>

示例:

Tips
需要注意,所谓的全局监听并不是所有组件的交互行为都可以被监听,对于鼠标事件,需要满足如下条件:

在回调中,可以通过回调参数的 componentTypecomponentSubType 等事件发生的具体位置,详情可参考 一节。

若提供了 query 参数,则 ECharts 在执行回调前,会先判断事件源是否满足过滤条件。 query 参数 string、object 两种形式,当使用字符串时,格式可以是 mainType、mainType.subType 两种形式,例如:

<!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">
			const myChart = echarts.init(document.getElementById('main'));
			const option = {
				xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] },
				yAxis: { type: 'value', min:  },
				series: [
					{ data: [, , , , , , ], type: 'bar' },
					{ data: [, , , , , , ], type: 'line' },
				],
			};

			myChart.setOption(option);

			// 在所有 series 上都触发
			myChart.on('click', 'series', function (e) {
				console.log(`series listener: click invoke at ${e.componentType}.${e.componentSubType}`);
			});

			// 只在 line 图表上触发
			myChart.on('click', 'series.line', function (e) {
				console.log(`line listener: click invoke at ${e.componentType}.${e.componentSubType}`);
			});
		</script>
	</body>
</html>

示例有两个 click 回调,第指定过滤参数为 series,将在所有图表发生单击事件时执行回调;第二个指定过滤参数为 series.line,则只在折线图发生单击事件时触发。示例:

query 还可以以对象方式传入,对象可以包含如下:

{
	<mainType>Index: number // 组件 index
	<mainType>Name: string // 组件 name
	<mainType>Id: string // 组件 id
	dataIndex: number // 数据项 index
	name: string // 数据项 name
	dataType: string // 数据项 type,如关系图中的 'node', 'edge'
	element: string // 系列中的 el 的 name
}

其中 mainType 为组件类型,如 seriesIndex、xAxisIndex 等。示例:

const option = {
	...
	series: [
		{ data: [, , , , , , ], type: 'bar', name: 'series1' },
		{ data: [, , , , , , ], type: 'line', name: 'series2' },
	],
};

myChart.on(
	'click',
	// 在 series1 上触发
	{seriesName:'series1'},
	function(e) {
	}
);

字符串与对象形式过滤的不同,字符串形式只能根据组件类型、子类型过滤;对象形式则精确到组件、数据项维度。继续看看示例:

<!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">
			const myChart = echarts.init(document.getElementById('main'));

			const option = {
				grid: { triggerEvent: true },
				xAxis: {
					type: 'category',
					data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
				},
				yAxis: {
					type: 'value',
				},
				series: [
					{
						data: [, , , , , , ],
						type: 'bar',
					},
				],
				title: { text: 'test' },
			};
			myChart.setOption(option);

			myChart.on('click', { dataIndex:  }, (e) => {
				console.log(`click invoke with data index: ${e.dataIndex}`);
			});
		</script>
	</body>
</html>

示例声明过滤参数为 { dataIndex: 1 },则只会在数据项 1 上触发,:

可通过 echartInstance.off 接触事件绑定,签名:

(eventName: string, handler?: Function)

handler 参数可选,若未提供该参数则解除所有 eventName 的事件监听。

ECharts 的事件系统设计的比较隐晦,有很多隐藏逻辑并没有表现在官方文档上,本文尝试对事件系统做个全局的介绍,总结重点如下:


联系我
置顶