1. 程式人生 > >完美解決echarts的柱狀圖和折線圖的點選非圖表圖形元素不會觸發事件

完美解決echarts的柱狀圖和折線圖的點選非圖表圖形元素不會觸發事件

在涉及到圖示的開發中,相信大家經常會用到echarts,echarts中可以通過on方法新增事件處理函式,可以很方便的實現一些互動。如:


但是直接新增的click事件,只有點選在圖形元素上才會觸發事件處理函式。以柱狀圖和折線圖為例:



在上述兩張圖中,只有點選柱狀圖形和折線的圓形折點才能觸發通過on新增的事件監聽,圖中標註的灰色區域並不能觸發點選。在資料差別很大的圖形中,想準確點選資料較小甚至為0的圖形是非常困難的,這就使得一些互動體驗不是很好。

想實現點選非圖形區域觸發事件,可以使用echarts提供的getZr()方法,但是該方法只能獲取到一些諸如點選位置之類的資訊,並且是整個canvas區域都會響應,並不能很方便的使用。

那麼,能不能實現點選灰色區域觸發繫結的事件呢,答案當然是可以的。

本文總結了三種實現方法,介紹如下:

1、利用tooltip記錄資訊,使用zr 監聽事件,進行事件處理。

這種方法是利用showTip方法或者tooltip的formatter函式記錄選中的資料資訊,並在zr監聽到的事件中以記錄的資訊來處理點選事件,彌補zr攜帶的資訊不便使用的缺陷,具體實現可參照這裡

這種方法可以實現想要的效果,但是需要不斷的記錄、更新資訊,影響效能。

2、 利用tooltip觸發時選中區域的axisPointer的formatter丟擲選中資料的相關資訊,並在回撥函式中進行資料處理。實現如下:

首先配置tooltip:

"tooltip": {

      "trigger":"axis",

      "triggerOn":"click"

},

在需要響應的座標軸配置axisPointer:

"axisPointer": {

        "value": 3,

        "lineStyle":{

          "color":"white",

          "opacity":0.8,

          "width": 3

        },

        "label": {

          "show":false,

         "formatter": ""

        },

        "zlevel": 4,

        "handle": {

          "show": true,

          "color":"white",

          "icon":"image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAATCAYAAACp65zuAAAAAXNSR0IArs4c6QAAAKhJREFUKBVjYEAD////FwZiTjRhVC5QQSEQ/wTij0DsgyoL5QElLIH4DxDDwAcgQx5DMVDwIEwFEr0ARSFQwh5JEpkJskEDrhjI2Yssi8ZeBVYIFLRGk0Dn/gMKGDIAiZ3oMlj4WxlBgnA34GEw4ZFDkWKB8RiBAMZGpmE2DiurQcHzHtmXONjvQQrrgPgvDgUg4X9AXAcOO2BYiQA5UiBRLOAZMIjfAAA9L+soE820hAAAAABJRU5ErkJggg==",

          "size": [

            10,

            16

          ],

          "margin":2

        },

        "triggerOn":"click"

     },

在setOption前進行formatter的覆蓋

tmp.xAxis.axisPointer.label.formatter= this.onAxisPointer.bind(this, this.reqParams);

option外面的處理函式如下

onAxisPointer(reqParams,params) {

     }

這種方法也可以很好的實現上述需求,缺點在於事件的觸發和tooltip的顯示必須同步,並不能實現mousemove顯示tooltip,click觸發事件,使用起來具有一定的侷限性。

3、 利用echarts提供的新API convertFromPixel完美解決。

這種方法藉助於convertFromPixel和zr來實現需要的效果,實現方法如下:

this.echart.getZr().on('click',params=>{
    const pointInPixel= [params.offsetX, params.offsetY];
    if (this.echart.containPixel('grid',pointInPixel)) {
        let xIndex=this.echart.convertFromPixel({seriesIndex:0},[params.offsetX, params.offsetY])[0];
        /*事件處理程式碼書寫位置*/

}
});

實現的程式碼解釋如下:

使用getZr新增圖表的整個canvas區域的點選事件,並獲取params攜帶的資訊:

this.echart.getZr().on('click',params=>{})

獲取到滑鼠點選位置:

const pointInPixel= [params.offsetX, params.offsetY];

使用containPixel API判斷點選位置是否在顯示圖形區域,下面的例子過濾了繪製圖形的網格外的點選事件,比如X、Y軸lable、空白位置等的點選事件。

if (this.echart.containPixel('grid',pointInPixel)) {}

使用API convertFromPixel獲取點選位置對應的x軸資料的索引值,我的實現是藉助於索引值的,當然可以獲取到其它的資訊,詳細請檢視文件

let xIndex=this.echart.convertFromPixel({seriesIndex:0},[params.offsetX, params.offsetY])[0];

其實在上一步驟中可以獲取到豐富的諸如軸線、索引、ID等資訊,可以在自己的事件處理程式碼中方便的使用。

這種方法僅響應圖表區域的響應事件,通過convertFromPixel獲取到可能需要的一些資訊,可以很好的實現需求,並且不會有其它的效能影響,完美實現瞭如題的需求。

我在工作中遇到了這樣的一個需求,通過一段時間的查資料、請教同事、檢視API總結了如上三種方法,並使用第三種方法解決了我的問題,特此記錄。