事件 - Event
Chart 对象中提供了非常丰富的生命周期事件和交互事件,开发者可以利用这些事件,去做业务自定义的扩展和交互。在 G2 中使用事件的方式如下所示:
chart.on('eventName', callback); // 绑定事件
chart.once('eventName', callback); // 绑定事件,只触发一次
chart.off('eventName', callback); // 移除事件
事件类别
在 G2 中,我们将事件分成为几种事件类型:
1. 基础事件
主要包含有 DOM 的基础事件。
-
mouse 事件
- mousedown
- mousemove
- mouseup
- mouseover
- mouseout
- mouseenter
- mouseleave
-
touch 事件
- touchstart
- touchmove
- touchend
- touchcancel
-
drag 事件
- dragenter
- dragover
- dragleave
- drop
- contextmenu 右键事件
- dblclick 双击事件
2. 组合事件
基础事件
中,只要画布中触发这些事件,都会执行,但是大部分场景下,我们需要精确定位到某一个元素的点击,比如:
- 柱形图的柱子被 click 的时候
- 图例的某一项被 hover 的时候
- 坐标轴的标签被 dblclick 的时候
- ...
这种情况我们就可以使用 G2 的组合事件,G2 的组合事件规则为:组件名:基础事件名
。
${componentName}:${eventName}
例如对应上述的几个场景,事件名称为:
- element:click
- legend-item:mouseover
- axis-label:dblclick
- ...
G2 内置的组件中,componentName 的分类很细,可以以下面的一个图进行大概说明。
也就是大致可以分成为:
- plot
-
axis
- axis-line
- axis-label
-
legend
- legend-item
- label
- slider
-
element
- interval
- line
- area
- point
- polygon
- schema
- voilin
- path
- ...
然后将这些组件名称和基础事件名进行一个排列组合,即为 G2 内置的事件。
图形 Element 上的事件
为了便于用户访问图形对应 Element 对象,可以通过 shape.get('element') 对象来获取,后面也会在 shape 上增加 delegateObject 对象来访问。
chart.on('element:click', (ev) => {
const shape = ev.shape;
const element = shape.get('element');
const data = element.getModel().data;
// to do something
});
为了帮助用户更加清晰的使用事件前缀(name),我们在这里列出 G2 默认支持的所有的事件前缀(name):
- element:所有的 geometry 的 element 都支持的事件前缀
- line: 折线图支持的前缀
- area: 面积图支持的前缀
- interval: 柱状图、直方图、饼图 等支持的事件前缀
- point:点图、气泡图等支持的前缀
- polygon:方块图等支持的前缀
- schema:k 线图、箱型图支持的事件前缀
- edge: 边支持的前缀
几点说明:
- 除了 element 是通用的事件前缀外,所有的 geometry 的 type 就是他们的事件前缀
- heatmap 由于未创建任何 element 所以不支持任何事件前缀
- element 上的获取返回的数据有些是单条数据,有些是一组数据的集合
chart.on('line:click', (ev) => {
const lineElement = ev.target.get('element');
const data = lineElement.getModel().data; // 数组
});
chart.on('interval:click', (ev) => {
const intervalElement = ev.target.get('element');
const data = lineElement.getModel().data; // 单条数据
});
Axis 事件
- axis-label:坐标轴文本的事件前缀
- axis-line:坐标轴轴线的事件前缀
- axis-tick:坐标轴刻度线的事件前缀
- axis-title:坐标轴标题事件前缀
chart.on('axis-label:click', (ev) => {});
Legend 事件
- legend:图例的事件前缀,无论点击了图例的任意图形上
- legend-title:图例标题的事件前缀
- legend-item:图例选项的事件前缀
- legend-item-name:图例选项 name 文本 的事件前缀
- legend-item-marker: 图例选项 marker 图标 的事件前缀
- legend-item-value:图例选项 value 的事件前缀
Annotation 事件
- annotation: 所有辅助图形共同的事件前缀
- annotation-line:辅助线的事件前缀
- annotation-line-text:辅助线上的文本的前缀
- annotation-image:辅助图形的事件前缀
- annotation-region:辅助区域的事件前缀
- annotation-text: 辅助文本的事件前缀
- annotation-html: html 辅助元素的事件前缀
- annotation-shape: G.shape 自定义辅助元素的事件前缀
Tooltip 事件
Tooltip 事件比较特殊,只有内置的几个事件,而不具备组合事件能力。
- tooltip:show
- tooltip:hide
- tooltip:change
3. Chart / View 生命周期事件
生命周期事件,只是画布在会绘制过程中的一些切面时间点,会抛出一些事件名称,这些名称主要包括:
- beforerender
- afterrender
- beforepaint
- afterpaint
- beforechangedata
- afterchangedata
- beforeclear
- afterclear
- beforedestroy
- beforechangesize
- afterchangesize
事件的含义和字面含义一致,这里不做过多冗余解释。这些生命周期名称作为事件名称可以直接被调用。
4. 状态事件
当 Element 上的状态发生改变时,会释放 'element:statechange' 时间,用户可以在 Chart/View 上监听该事件。
chart.on('element:statechange', (eventObject) => {});
用户可以在上述 eventObject 属性中获取触发该事件的 element,当前的状态以及状态值:
const { element, state, stateStatus } = eventObj.gEvent.originalEvent;
然后基于这些做一些自定义交互和扩展。
事件实例
chart.on('eventName', (evt) => {
const { type, view, gEvent, data, x, y, clientX, clientY } = evt;
// type 事件名称
// view 触发事件的 View 实例
// gEvent 底层渲染引擎 G 的事件实例
// data 对于点击图形的时候,这里会包含有点击图形的数据
// x,y 鼠标点击位置
// clientX, clientY 鼠标点击 client 位置
const { target } = gEvent;
// target 实际触发点击的 G UI 实例
});
所有组件上的事件都可以在 target 上拿到 delegateObject,这上面有组件或者组件选项的信息,所有的组件事件都有 component 属性,其他的属性不同的事件不一样:
chart.on('legend-item:click', (ev) => {
const target = ev.target;
const delegateObject = target.get('delegateObject');
const item = delegateObject.item; // 图例选项
});
chart.on('legend:valuechange', (ev) => {
const target = ev.target;
const delegateObject = target.get('delegateObject');
const component = delegateObject.component;
const value = component.getValue(); // 选中的文本范围
});
在上述的使用方式中,监听事件的回调函数,只有一个参数,也就是 G2.Event 实例,其中的有效信息可以见上述代码中的注释内容。利用上述内容,就可以根据交互事件作为触发源,然后结合事件 evt 对应的数据和实例 API,即可以实现业务自定义的交互和扩展能力了。