前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >读者提问,如何让 tooltip 提示框内显示饼图

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

作者头像
ZXand618
发布2022-04-10 10:14:54
1.5K0
发布2022-04-10 10:14:54
举报

效果截图

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

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

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

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

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

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

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

通过回调函数返回一个带 id 属性的 div,比如

以这个 div 为容器,初始化 ECharts 实例;

根据触发提示框的 params 属性,准备相应的饼图配置项,渲染对应的饼图

大体思路图示

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

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

问题 1

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

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

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

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

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

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

第 1 种思路尝试失败

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

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

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

  • 通过「setInterval」每隔一段时间(比如 10 毫秒),判断是否存在提示框饼图的空容器(div),如存在则触发饼图的重新渲染。
代码语言:javascript
复制
// 准备一个饼图的 option
let 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}<br/><div id="tooltipPie" style="width: 100px;height:100px;"></div>`;
        }
    },
    series: [{
        type: 'bar',
        stack: 'stack1',
        data: [220, 182, 191, 234, 290, 330, 310]
    }, {
        type: 'bar',
        stack: 'stack1',
        data: [120, 122, 91, 324, 113, 130, 410]
    }, {
        type: 'bar',
        stack: 'stack1',
        data: [42, 32, 29, 72, 31, 63, 101]
    }]
};


/**
 * 因为每次弹出/移动提示框,都会覆盖提示框 DOM,所以只能每次都重新渲染饼图
 * (暂且使用了个笨办法 setInterval,10 毫秒判断处理一次 = =b,有时间再想想更好的方式)
 */
setInterval(function(){
    if (document.getElementById('tooltipPie') !== null && document.getElementById('tooltipPie').innerHTML === '') {
        if (typeof tooltipChart !== 'undefined') {
            return tooltipChart.setOption(pieOption);
        }
        var tooltipChart = echarts.init(document.getElementById("tooltipPie"));
        tooltipChart.setOption(pieOption);
    }
},10);

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ZXand618的ECharts之旅 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档