在Echarts区域的任何位置精准触发事件
需求背景:点击Echarts区域跳转页面,跳转的区域不包括grid的坐标及标签,翻看了Echarts官网,实现触发事件之的on方法,但是此方法只能在鼠标点击某个图形上会触发,这样并不能实现需求。通过百度和查看github issue后多用Echarts实例的getZr()方法监听到整个画布的 click 事件。
使用echartsInstance.getZr().on('click' , params => {})监听画布,配合echartsInstance.containPixel('grid', pointInPixel) 方法判断点击位置是否在坐标系里面,从而解决需求问题。
但是getZr()官方文档并没解释。所以下面将分享两个点击事件的场景,一:点击某个图形触发点击事件,二:点击任意位置触发点击事件并且知道自己点击的位置,处理折线不易点击的情况。
一. 场景一 : 点击图形触发点击事件
1.echartsInstance.on()
鼠标点击某个图形上会触发点击事件使用on方法
图形为折线上的折点,柱状图的柱子等等。折线,坐标轴的标签,坐标轴内的空白位置是不会触发点击事件。
可选参数有:
参数一:事件名称 eventName
eventName: string,//事件名称,全小写,例如'click','mousemove', 'legendselected'
参数二:过滤条件 query
query: string|Object,//可选的过滤条件,能够只在指定的组件或者元素上进行响应。可为 string 或者 Object。
如果为 string
表示组件类型。格式可以是 'mainType' 或者 'mainType.subType'。例如:
chart.on('click', 'series', function () {...});
chart.on('click', 'series.line', function () {...});
chart.on('click', 'dataZoom', function () {...});
chart.on('click', 'xAxis.category', function () {...});
如果为 Object
,可以包含以下一个或多个属性,每个属性都是可选的:
{
<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
}
例如:更多案例移步官网
chart.setOption({
// ...
series: [{
name: 'uuu'
// ...
}]
});
chart.on('mouseover', {seriesName: 'uuu'}, function () {
// series name 为 'uuu' 的系列中的图形元素被 'mouseover' 时,此方法被回调。
});
参数三:事件处理函数 handler
handler: Function,//(params)=>{}
参数四: context
可选。回调函数内部的context
,即this
的指向。
2.鼠标事件参数:
通过参数获取点击位置的数据
鼠标事件的事件参数是 事件对象的数据 的各个属性,通过参数获取点击位置的数据,对于图表的点击事件,基本参数如下,其它图表诸如饼图可能会有部分附加参数。例如饼图会有percent
属性表示百分比,具体见各个图表类型的 label formatter 回调函数的 params
。
{
// 当前点击的图形元素所属的组件名称,
// 其值如 'series'、'markLine'、'markPoint'、'timeLine' 等。
componentType: string,
// 系列类型。值可能为:'line'、'bar'、'pie' 等。当 componentType 为 'series' 时有意义。
seriesType: string,
// 系列在传入的 option.series 中的 index。当 componentType 为 'series' 时有意义。
seriesIndex: number,
// 系列名称。当 componentType 为 'series' 时有意义。
seriesName: string,
// 数据名,类目名
name: string,
// 数据在传入的 data 数组中的 index
dataIndex: number,
// 传入的原始数据项
data: Object,
// sankey、graph 等图表同时含有 nodeData 和 edgeData 两种 data,
// dataType 的值会是 'node' 或者 'edge',表示当前点击在 node 还是 edge 上。
// 其他大部分图表中只有一种 data,dataType 无意义。
dataType: string,
// 传入的数据值
value: number|Array,
// 数据图形的颜色。当 componentType 为 'series' 时有意义。
color: string,
// 用户自定义的数据。只在 graphic component 和自定义系列(custom series)
// 中生效,如果节点定义上设置了如:{type: 'circle', info: {some: 123}}。
info: *
}
场景二 . 任意位置触发点击事件:
echartsInstance.getZr().on('click' , params => {})监听整个画布的点击事件。
参数params如下:
注意,不同版本的echarts参数不一样,本次使用的是echarts@4.2.1
1.使用参数,知道点击位置
- 通过参数对象中的target属性和topTarget属性进行定位位置
- 当点击某个图形元素:target对象中有dataIndex,seriesIndex属性,即可知道点击那个图形元素。
- 当点击grid内的空白位置:target对象为undefined,topTarget不为undefined。
- 当点击坐标轴标签:topTarget对象的anid值为"label_xx", xx为坐标值。
- 当点击坐标轴外的空白位置:target对象和topTarget多为undefined。
因为官方并没对getZr()方法进行解释,所以只能观察参数的差异去实现点击的位置的获取。
2.getZr()配合containPixel()方法判断给定点的位置
echartsInstance.containPixel() 判断给定的点是否在指定的坐标系或者系列上。
语法如下:
(
// finder 用于指示『在哪个坐标系或者系列上判断』。
// 通常地,可以使用 index 或者 id 或者 name 来定位。
finder: {
seriesIndex?: number,
seriesId?: string,
seriesName?: string,
geoIndex?: number,
geoId?: string,
geoName?: string,
xAxisIndex?: number,
xAxisId?: string,
xAxisName?: string,
yAxisIndex?: number,
yAxisId?: string,
yAxisName?: string,
gridIndex?: number,
gridId?: string
gridName?: string
},
// 要被判断的点,为像素坐标值,以 echarts 实例的 dom 节点的左上角为坐标 [0, 0] 点。
value: Array
) => boolean
目前支持在这些坐标系和系列上进行判断:grid, polar, geo, series-map, series-graph, series-pie。
例:
// 判断 [23, 44] 点是否在 geoIndex 为 0 的 geo 坐标系上。
chart.containPixel('geo', [23, 44]); // 'geo' 等同于 {geoIndex: 0}
// 判断 [23, 44] 点是否在 gridId 为 'z' 的 grid 上。
chart.containPixel({gridId: 'z'}, [23, 44]);
// 判断 [23, 44] 点是否在 index 为 1,4,5 的系列上。
chart.containPixel({seriesIndex: [1, 4, 5]}, [23, 44]);
// 判断 [23, 44] 点是否在 index 为 1,4,5 的系列或者 gridName 为 'a' 的 grid 上。
chart.containPixel({seriesIndex: [1, 4, 5], gridName: 'a'}, [23, 44]);
getZr()配合containPixel()例子:
判断点击位置是否在grid中:(this.line为echartsInstance)
this.line.getZr().on('click', params => {
let pointInPixel = [params.offsetX, params.offsetY]
console.log(this.line.containPixel('grid', pointInPixel))
})
3.处理折线不易点击的情况:
折现图设置点击事件时,只能点击折点,有时并不容易点击,可以配合axisPointer的shadow指示器方便点击。
this.line.getZr().on('click', params => {
const pointInPixel = [params.offsetX, params.offsetY]
// 使用 convertFromPixel方法 转换像素坐标值到逻辑坐标系上的点。获取点击位置对应的x轴数据的索引 值,借助于索引值的获取到其它的信息
let pointInGrid = this.line.convertFromPixel({ seriesIndex: 0 }, pointInPixel)
// x轴数据的索引值
let xIndex = pointInGrid[0]
// 使用getOption() 获取图表的option
let op = this.line.getOption()
// 获取当前点击位置要的数据
var xData = op.series[0].data[xIndex]
})
注:
echartsInstance.convertFromPixel()方法:链接。
echartsInstance.getOption()方法:链接。