嵌套饼图_读者提问,如何让 tooltip 提示框内显示饼图

74de76c702755ed3e9035fb4790d35ad.png

效果截图

前些天有读者问,ECharts 的提示框(tooltip)内,能不能添加一个饼图?

我之前倒是看到过用饼图作为散点图数据点的例子,感觉应该有办法……但是提示框和那个不太一样,估计需要研究一下——所以先回复说,这个之前没有尝试过,我有空试一下。

实现思路(一段曲折的过程)

当天晚上有事,没来及看,转天上班途中,先看了眼配置项手册,在确认没有现成功能可用的同时,注意到了一个关键点:提示框是一个 DOM 节点,也就是有办法作为 ECharts 的容器。

浮层的渲染模式,默认以 'html 即额外的 DOM 节点展示 tooltip;此外还可以设置为 'richText' 表示以富文本的形式渲染,渲染的结果在图表对应的 Canvas 中(目前 SVG 尚未支持富文本),这对于一些没有 DOM 的环境(如微信小程序)有更好的支持。

「ECharts 配置项手册」

https://echarts.apache.org/zh/option.html#tooltip.renderMode

另外,其实从「tooltip.formatter」默认的换行符是「
」而不是「」这一个特点上,也可以推测得到的。

有了这个关键点,大体的思路就有了:

  • 通过回调函数返回一个带 id 属性的 div,比如
  • 以这个 div 为容器,初始化 ECharts 实例;
  • 根据触发提示框的 params 属性,准备相应的饼图配置项,渲染对应的饼图
009a728ed74d0ddc31bac608663396f2.png

大体思路图示

但是还存在一个问题需要解决,这个问题有 2 个难点:

  • 在提示框首次弹出之前,带 id 的 div(回调函数返回的「饼图容器」)是不存在的,而且每次触发提示框显示/移动,这个 div 会被覆盖,也就是渲染好的「canvas」元素会消失——所以每次触发 tooltip,都需要重新渲染饼图;
90bea5e3fc35974fd5883c33d3e66386.png

问题 1

  • 从ECharts API 看,提示框的显示、隐藏,并没有事件可供监听,也没办法把这个动作加到「tooltip.formatter」的回调函数中,因为「问题 1」的覆盖,发生在函数返回结果之后。

为了解决这个问题,我想到了 2 种尝试的思路:

  1. 通过监听「events.finished」事件,主图表渲染动作完成后,如果存在提示框饼图的容器(div),则触发饼图的重新渲染;
  2. 通过回调函数的嵌套,在「tooltip.formatter」的回调函数中,再嵌一个 callback,加一定延时后渲染饼图。

然后我就开始尝试有可能最简单的第 1 种,结果发现提示框中的饼图时有时无……然后经过各种分析,打点、测试、翻源码(其实没咋看懂= =b),明白了大致原因:

提示框(tooltip)的移动,不触发「events.finished」事件,也就是当提示框指示的数据项/数据轴没发生改变时,提示框发生了「move」,而不是先「hide」再「show」

  • 「tooltip.formatter」的回调函数执行,提示框层(div)的位置变了,提示框里的饼图没了(回调函数 return 了新的「饼图容器」);
  • 「events.finished」事件没有发生,新的饼图没有补上……

第 1 种思路尝试失败-_-b

然后开始试图尝试第 2 种,但作为一个先接触 ECharts 后接触 JavaScript 的 JS 小白,我毫无悬念地、稀里糊涂地失败了

各位前端大神们,有兴趣的话,可以亲自尝试一下,我就不班门弄斧了……

被 callback 虐了半天的自己,郁闷了 10 多分钟……然后终于,自暴自弃地,想到了简单暴力的第 3 种方法:

  • 通过「setInterval」每隔一段时间(比如 10 毫秒),判断是否存在提示框饼图的空容器(div),如存在则触发饼图的重新渲染。
// 准备一个饼图的 optionlet pieOption = {    series: {        type: "pie",        labelLine: {            show: false        },        label: {            show: false         }    },    animation: false};option = {    title: {        text: '读者提问,提示框能否显示饼图'    },    xAxis: {        data: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']    },    yAxis: {},    tooltip: {        trigger: 'axis',        formatter: params => {            // 根据触发提示框的数据,准备饼图数据            let pieData = [];            for (let i in params) {                pieData.push({                    name: params[i].seriesName,                    value: params[i].value,                    color: params[i].color                });            }                        // 将饼图数据存入饼图 option.series.data            pieOption.series.data = pieData;            return `${params[0].axisValue}

就是这段,每隔 10 毫秒,检测一次提示框饼图容器的内部是否为空,如果是,就重新渲染一遍饼图,这次算是非常不优雅的成功了-_-o

点击「了解更多」查看 ECharts Gallery 例子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值