在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参数不一样,本次使用的是[email protected]

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()方法:链接

02-10 22:25