「Echarts 实践」Echarts 柱状图点击事件的实现方法【超实用方案 建议点赞收藏】

在前端开发过程中,柱状图举例应用突出:例如点击柱形区域时,完成相关操作或跳转至指定界面。尽管Echarts提供了丰富的事件监听机制,但在实现过程中,不同场景对点击调用的需求不完全相同。
本文将详细介绍如何实现柱状图点击事件,并提供实现整条柱形区域点击的方法。


一、需求

领导:这个图表上的点击事件不好操作,特别是在柱状图上点击时,我无法点中!
我:改!像这样在空白处有图例显示时就能点中可以吧?
领导:棒!你小子,前途无量!就这么改

具体实现请移步至【实现二】
在这里插入图片描述

实现一、简单点击事件

如果只需要实现点击柱状图中有数据的部分,可以通过 myChart.on监听事件:

myChart.on('click', function (params) {
    console.log(params);
});

这个方法将返回所点击柱状区域对应的数据,例如点击一条柱形,params 属性中将包含其对应的值(value)和名称(name)。

如果需要将柱形值上添加更多属性,可以在 series 的数据实例中使用对象进行定义:

seriesData: [
    { value: 1, id: 'ID_1' },
    { value: 2, id: 'ID_2' },
    // ...
]

将以上数据添加到Echarts柱状图后,在点击事件中,params 属性中同样可获取到自定义的数据,如下手动打印ID:

myChart.on('click', function (params) {
    console.log(params.data.id); // 输出点击柱状区域对应的ID
});

然而,该方法存在一个问题:点击仅限于有值的柱状部分,而对于柱状空白区域,点击无效。


实现二、实现整条柱形区域点击

前置讲解

1. ZRender

在 ECharts 中,点击空白区域(即未绑定数据的区域)默认并不会触发 click 事件,但是 ECharts 使用 ZRender 作为其渲染引擎,提供了对整个画布进行事件监听的能力。你可以通过监听底层的渲染引擎(ZRender)的 click 事件来捕获整个画布上的点击事件,包括空白区域。

也就是说,可以通过 myChart.getZr() 返回 ZRender 实例,然后监听它上面的 click 事件,通过这种方式,就可以捕获到整个图表区域内的所有点击事件,无论是否在数据或图形上点击。

myChart.getZr().on('click', params => {
	console.log(params)
}

myChart.getZr() 打印一下里面的参数:
在这里插入图片描述

这里面有用的参数就是 offsetXoffsetY,这两个是当前鼠标位置相对整个Echart 边框的水平和垂直方向上的偏移量。
根据这两个参数,我们就可以确定了鼠标当前的位置,然后在鼠标所有位置的垂直线上,肯定相交了一条数据,这条数据的 x 轴就可以拿到了,然后通过这个 x 轴的关系找到折线上的真实数据

2. containPixel

这里用到一个 api:containPixel

官方文档上有说明:判断给定的点是否在指定的坐标系或者系列上。

containPixel 是 ECharts 提供的一个方法,用于判断一个像素点是否在某个组件(如图表网格、坐标系等)内。这对于实现图表的交互功能非常重要,尤其是在需要判断鼠标点击、拖动等行为是否发生在特定区域时。

3. convertFromPixel

这里还有一个关键的api:convertFromPixel

官方文档上有说明:转换像素坐标值到逻辑坐标系上的点。

也就是说,虽然当前点击位置没有折线经过,但我们也可以通过前面点击获取的偏移值 offsetXoffsetY 计算出当前点在坐标轴上的真实x、y值,这个x值就是我们要的,通过这个x值我可以遍历y轴对应的 series 中的值,找到y值value。

功能实现

如果需要实现整条柱状区域的点击,不限于柱状中有值的部分,可以使用 getZr()注册全屏点击事件:

myChart.getZr().on('click', params => {
    const pointInPixel = [params.offsetX, params.offsetY];
    const pointInGrid = myChart.containPixel('grid', [params.offsetX, params.offsetY]);
    // 判断点击位置是否在柱状图内
	if (pointInGrid) {
          // 转换点击的像素点为数据索引
          const coord = myChart.convertFromPixel({ seriesIndex: 0 }, [params.offsetX, params.offsetY]);
          if (coord && coord[1] !== undefined) {
          	// 获取 Y 轴的索引
            const dataIndex = Math.round(coord[1]); 
            console.log(dataIndex);
            // 拿到了dataIndex ,就可以直接从数据中获取需要的内容了
            // 下面只是简单举个例子【👇 添加ID支持】,至此,就需要根据自己的业务逻辑来开发啦
        }
});

示例:添加ID支持

如需要通过点击位置获取柱状数据对应的ID,可以通过 series 数据配置,配合按照对应索引获取:

seriesData: [
    { value: 1, id: 'ID_1' },
    { value: 2, id: 'ID_2' },
    // ...
]

myChart.getZr().on('click', params => {
    let pointInPixel = [params.offsetX, params.offsetY];
    const pointInGrid = myChart.containPixel('grid', [params.offsetX, params.offsetY]);
	if (pointInGrid) {
          const coord = myChart.convertFromPixel({ seriesIndex: 0 }, [params.offsetX, params.offsetY]);
          if (coord && coord[1] !== undefined) {
            const dataIndex = Math.round(coord[1]); 
	        const id = seriesData[dataIndex ]?.id;
	        console.log(id); // 输出点击的柱状对应ID
        }
});

进阶扩展

如需要扩展功能,如操作与柱状区域相关的其他元素,可配合使用屏幕坐标和图位转换,实现更维度操作:

myChart.getZr().on('click', params => {
    const pointInPixel = [params.offsetX, params.offsetY];
    const pointInGrid = myChart.containPixel('grid', [params.offsetX, params.offsetY]);
	if (pointInGrid) {
        let [xIndex, yIndex] = myChart.convertFromPixel({ seriesIndex: 0 }, [params.offsetX, params.offsetY]);
        console.log(`xIndex: ${xIndex}, yIndex: ${yIndex}`);
        // 基于事件调用实现进阶操作
    }
});

总结

通过Echarts提供的事件监听机制,我们可以实现点击柱状图中指定值的事件,也可以通过全屏监听实现整条柱状区域的监听,同时尽可能扩展事件功能,并为下步功能实现打下基础。

以下是ExtJS整合Echarts实现柱状图,并实现柱状图点击事件的示例代码: ```javascript // 定义ExtJS的store var store = Ext.create('Ext.data.Store', { fields: ['name', 'value'], data: [ { name: 'Mon', value: 120 }, { name: 'Tue', value: 200 }, { name: 'Wed', value: 150 }, { name: 'Thu', value: 80 }, { name: 'Fri', value: 70 }, { name: 'Sat', value: 110 }, { name: 'Sun', value: 130 } ] }); // 定义Echarts的option var option = { xAxis: { type: 'category', data: store.collect('name') }, yAxis: { type: 'value' }, series: [{ data: store.collect('value'), type: 'bar' }] }; // 定义ExtJS的panel var panel = Ext.create('Ext.panel.Panel', { width: 600, height: 400, renderTo: Ext.getBody(), layout: 'fit', items: [{ xtype: 'chart', store: store, axes: [{ type: 'numeric', position: 'left', fields: ['value'], title: { text: 'Value', fontSize: 15 }, grid: true }, { type: 'category', position: 'bottom', fields: ['name'], title: { text: 'Name', fontSize: 15 } }], series: [{ type: 'bar', xField: 'name', yField: 'value', listeners: { itemclick: function(series, item, event) { // 点击事件处理 console.log(item.record.get('name') + ': ' + item.record.get('value')); } } }] }], listeners: { afterrender: function() { // 渲染Echarts var chart = this.down('chart'); chart.setOption(option); } } }); ``` 在上述代码中,我们首先定义了一个ExtJS的store,用于存储数据。然后定义了Echarts的option,包括x轴、y轴和series。接着定义了一个ExtJS的panel,包含一个chart组件,用于显示Echarts图表。在chart组件中,我们定义了x轴、y轴和series,并添加了一个itemclick事件监听器,用于处理柱状图点击事件。最后,在panel的afterrender事件中,我们渲染了Echarts图表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八了个戒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值