完美解決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總結了如上三種方法,並使用第三種方法解決了我的問題,特此記錄。