前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Echarts 添加多个 label 与动态调整 position 的方案

Echarts 添加多个 label 与动态调整 position 的方案

作者头像
Alan Zhang
发布2019-09-16 18:44:22
13.8K0
发布2019-09-16 18:44:22
举报
文章被收录于专栏:Alan's Lab

首先这是一个柱状堆积图,每一条柱子有两部分堆积形成。介绍一下数据意义方便理解需求:

一条柱代表一个任务,左半边的长度代表完成任务人数的比例,右半边的长度代表未完成任务人数的比例,加起来必定是 100% ,所以每条柱子都一样长占满整行。柱子内的数字为具体人数,最右侧百分比为完成人数的比例。

我们快速实现一个差不多的图表:

代码语言:javascript
复制
const myChart = echarts.init(document.getElementById('main'));

const option = {
  dataset: {
    source: [
      ['任务名', '完成率', '未完成率', '完成人数', '未完成人数'],
      ['任务1',  50,      50,       5,         5],
      ['任务2',  4,       96,       2,         50]
    ]
  },
  yAxis: {
    type: 'category'
  },
  xAxis: {},
  grid: {
    containLabel: true
  },
  series: [
    {
      type: 'bar',
      stack: 'samestack',
      label: {
        show: true,
        position: 'insideRight',
        formatter: '{@[3]}'
      }
    },
    {
      type: 'bar',
      stack: 'samestack',
      label: {
        show: true,
        position: 'insideRight',
        formatter: '{@[4]}'
      }
    }
  ]
};

myChart.setOption(option);

看起来像是这样:

这个图表有两个问题:

  1. echart 中没有办法简单添加最右侧的百分比 label
  2. 左半边柱子在数量太小的时候没空间容纳数字

前面说了 echarts 没法设置多个 label ,但它支持相当强大的富文本配置。对于第一个问题,我们可以通过富文本标签模拟一个额外的 label 。首先,修改右半边柱子的 formatter ,让完成率也显示在同一个 label 中。

代码语言:javascript
复制
[
      {
      // 左半边...
    },
      {
      type: 'bar',
      stack: 'samestack',
      label: {
              show: true,
        position: 'insideRight',
        formatter: '{people|{@[4]}} {percentage|{@[1]}%}',
        rich: {
            people: {
                  color: 'white'
          },
          percentage: {
                  color: 'red'
          }
        }
      }
    }
]

效果如下:

要把红色的百分比移出柱子外需要 label.distancerich.percentage.width 两个配置:

通过 width 给 percentage 这一个文本块一个固定的宽度,再给 distance 设置赋值配合 position: 'insideRight' 就可以让百分比的文本移出柱子外面。宽度设置为多少并不重要,因为文本是左对齐且没有超出裁剪,所以只要保持一致即可:

代码语言:javascript
复制
label: {
      show: true,
    position: 'insideRight',
    distance: -1,
    formatter: '{people|{@[4]}} {percentage|{@[1]}%}',
    rich: {
        people: {
              color: 'white'
      },
      percentage: {
              color: 'red',
        width: 1
      }
    }
  }

效果如下:

到这里第一个问题就解决了,可以继续细调以完全还原设计稿。

我们现在继续看一下另一个问题:如果柱子太窄,柱子内的文本会没有充足空间显示完。

以左半边柱子为例,为了让它在数值较小的情况下也能完全显示,我希望它在 20% 以下的时候显示在柱子外,20%或以上的时候才显示在柱子内,如下图所示:

同样,这个功能也没有现成的, echarts 也不支持针对单个柱子动态改变 label.position 配置。但我们可以通过预先计算出内部、外部要显示的内容,并在 dataset 中增加额外字段的方式达到这个目的。首先可以先通过 js 为 dataset 扩展两个字段:

代码语言:javascript
复制
const options = {
    dataset: {
          source: [
      ['任务名', '...', '已完成(内部)', '已完成(外部)'],
      ['任务1',  '...', 50,            '看不见我'],
      ['任务2',  '...', '看不见我',      2]
    ]
  },
  // ...
}

表中的 '看不见我' 仅为演示所用,实际使用中使用空字符串即可。

然后用解决第一个问题相同的方式,在一个 label 中同时显示“已完成(内部)”和“已完成(外部)”两个字段的内容,就可以完成这个需求(没这么简单):

代码语言:javascript
复制
[
      {
          // ...
      label: {
          // ...
        distance: -0,                                  // 3
        formatter: '{inside|{@[5]}}{outside|{@[6]}}',  // 1
        rich: {
            inside: {
                  color: 'white',
            width: 0,                                  // 3
            align: 'right'                             // 2
          },
          outside: {
                  color: 'red',
            width: 0,                                  // 3
            align: 'left'                              // 2
          }
        }
      },
      z: 4                                             // 4
    },
      {
        // 右半边柱子...  
    }
]

我们给左半边柱子的 label 定义了两个富文本格式:insideoutside

  1. formatter 中同时显示已完成(内部)已完成(外部)的内容,但总有其中一个是空字符串,以起到选择性渲染在柱子内部或外部的作用。
  2. inside 右对齐,文字变多时向左边生长,outside 相反
  3. 前面说过 width 具体数值不重要,设置成 0 也是没有问题的
  4. 由于左边柱子先渲染,会被右边盖住,所以提高 z 值让左边柱子的 label 高于右半边不被遮挡

得到的效果如下:

发生了什么。。。文本对齐的配置没有生效,全部变成居中挤在一起了。略经搜索之后了解到是 ZRender 的一个 bug 导致的。先不去深究,具体在这个例子中的表现是 formatter 中排前面的不能右对齐,排后面的不能左对齐。

那快速 hack 一下在 formatter 中把内外部渲染标签的顺序调换就好了。顺便把 dataset 中的 '看不见我' 改成 '' 以查看最终的效果。

代码语言:javascript
复制
{
    // ...
    // outside 放前面,inside 换到后面
    formatter: '{outside|{@[6]}}{inside|{@[5]}}',
    // ...
}

至此我们完美还原了设计稿,并且还优化了一个它未考虑到的边界条件。考虑到篇幅,还有一些旁枝末节的还原工作全都省略掉了,最终效果如下(请脑补最开头那张蓝色图表):

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档