ECharts——之二 表盘占比的显示 ECharts进阶使用 环形图绘制

本文介绍了使用ECharts实现环形图时如何处理表盘占比显示,包括两种方法的实现及存在的问题。第一种方法通过设置四组数据并隐藏部分实现,第二种方法通过两个饼图重叠。文章详细分析了两种方法的思路,并提出了各自的问题,如层级显示、响应式布局等,并给出了部分代码示例。
摘要由CSDN通过智能技术生成

时间:2018年11月——实践出真知

一、实际效果图

第一种,连接处特写

 

第二种,连接处特写

两种方法在显示时的思路不太一样,而且两种方法在显示的时候都有一点小瑕疵,也可以说是bug。

二、分析一下

先说第二种:第二种的实现思路是使用两个pie(饼图)进行重叠,将下面的颜色设置浅一点,上面的颜色设置深一点,然后按照顺序声明组件(颜色浅的的先声明,颜色深的后声明)。

再说第一种:第一种的实现思路中并没有用到第二个饼图,而是沿用了和隐藏环形饼图下面不显示部分一样的思路(也就是整个圆环下面空出来的部分),饼图在数据上其实是有四组的(从最下面的空白开始,顺时针:【空白】、【高亮】、【空白】、【隐藏】),但是显示的只有两组。也就是图表下方开口和高亮和正常之间的空隙这两个部分是给了满的透明度,所以显示为背景色。

再说说两种实现的bug,希望大家一起集思广益,欢迎将解决思路和方法在评论中留下来。

第二种的bug刚才说到了第二种的思路,那么最最关键的问题就是如何保证颜色深的一定在上面呢?在一开始我们按照声明顺序的原因让他满足我们的需求进行了显示,但是在ECharts中饼图有默认的高亮显示,当我们将鼠标移动到颜色浅的那一个pei上时,浅色的会覆盖掉颜色深的部分,展示一下实际图:

很明显是覆盖了,所以随之而来的两个解决思路就是:a:设置层级。b:设置下面的pei的鼠标悬浮事件,去掉默认的高亮显示。

然后针对两个方向我都进行了尝试的解决,a:对照文档给出z、zlevel属性参数,结果都没有用。b:移除了emphasis属性及参数,没有效果,对照文档关闭legendHoverLink和hoverAnimation也依旧没有作用。

但是我觉得按照我现在的理解其实这个问题应该是可以解决的,只不过可能会稍稍复杂一点,比如,设置渐变色,让在这个节点之前的都透明,然后后面的部分按照渐变色给出,减弱层次感,应该也能达到效果。或者按照网上一些博主给出的做法,去掉ECharts中给出的文件中的pei图的高亮那一块的代码。但是这些我觉得都不是最佳的解决办法,希望有人能够帮忙解决。

第一种的bug第一种的问题呢,就是细节部分的问题了,因为我们其实给出的是四组数据,而且在显示的两组数据中间还有一组隐藏的数据,那么问题所在就是在于响应式布局中的,不同页面显示的效果有差异的问题了。bug实际图:

显而易见,给中间部分进行隐藏是有问题的,那么随之而来的解决思路就是将定值变成比例值。

那么比例值应该是和什么有关的呢?明显就是页面的大小,而且和绘制图表的半径是紧关联的,而查阅文档之后,半径的的值是根据页面上较短的一边来设置的。所以先定位到半径,然后用算法算出大概可以接受的这一段的弧长,然后获得这一段在整个的比例值,就可以知道这一段应该给的值了。【理论上的,没有去具体实现,实现了的大佬,可以把实现链接发下呗,哈哈~!】

三、ECharts实现第一种

相信能够到做这个表的都是已经对ECharts有一定了解了的,如果没有了解过的请先去做一些更加简单的图表以后再来吧。

话不多说,先贴代码:

option = {
      title: {
        text: '体检信息',
        textStyle: {
          fontSize: 12, //图表标题字号
        }
      },
      series: [{
        name: '体检信息-底',
        type: 'pie',
        radius: ['69.5%', '70%'], //饼图的内外半径
        center: ['50%', '50%'], //圆心坐标
        avoidLabelOverlap: false, //是否启用防止标签重叠策略  默认true
        startAngle: 270 - angleOpen / 2, //起始角度,支持范围[0, 360]。   默认90
        legendHoverLink: false, //是否启用图例 hover 时的联动高亮   默认true
        hoverAnimation: false, //是否开启 hover 在扇区上的放大动画效果  默认true
        clockwise: true, //饼图的扇区是否是顺时针排布   默认true
        label: {
          show: false,
        },
        emphasis: {
          color: '#d9f0e1',
          borderColor: '#d9f0e1',
          borderWidth: 5,
        },
        data: dataDispose,//重点在这里
      }]
    };

没错,你没有看错,在主体里面并没有最最重要的部分,在这里仅仅声明了我们需要的pei,给出了一些开关。那么重点来了:

//参数设置
var point = 62.2; //获得的分数,限定:(0,totalPoint)
var totalPoint = 100; //总分 假设100
var angleOpen = 79.2; //开口角度:
var angleHide = 1.5; //两段之间的间隔
var setBorderWidth = 4; //图表宽度
//算法设定:
var anglePoint = (360 - angleOpen - angleHide) * point / totalPoint;
var angleTotalPoint = (360 - angleOpen - angleHide) * (1 - point / totalPoint);
var dataDispose = [{
        value: anglePoint,
        name: point,
        cursor: 'default',
        zlevel: 2,
        label: {
          show: true,
          position: 'center',
          formatter: [
            '{a|' + point + '}',
            '{b|得分}'
          ].join('\n'),
          rich: {
            a: {
              fontSize: 40, //设置分数显示的字号
              color: 'black', //设置分数显示的颜色
              fontWeight: 'normal', //设置分数显示的样式 'normal' 'bold' 'bolder' 'lighter'
            },
            b: {
              color: '#eaae4f',
              fontSize: 22, //设置文字的字号
              height: 40, //设置文字的高度
            },
          }
        },
        itemStyle: {
          normal: {
            color: '#40b66b',
            borderWidth: setBorderWidth, //描边线宽
            borderColor: '#40b66b', //图形的描边颜色
          },
          emphasis: {
            color: '#40b66b',
            borderColor: '#40b66b',
            borderWidth: setBorderWidth,
          },
        }
      }, { //不可修改
        value: angleHide,
        cursor: 'default',
        itemStyle: {
          label: {
            show: false,
          },
          labelLine: {
            show: false,
          },
          color: 'rgba(0, 0, 0, 0)',
          borderColor: 'rgba(0, 0, 0, 0)',
          borderWidth: 0,
        }
      }, {
        value: angleTotalPoint,
        name: '底色',
        cursor: 'default',
        itemStyle: {
          normal: {
            color: '#d9f0e1',
            borderWidth: setBorderWidth, //描边线宽
            borderColor: '#d9f0e1', //图形的描边颜色
          },
          zlevel: -1,
          legendHoverLink: false,
          emphasis: {
            color: '#d9f0e1',
            borderColor: '#d9f0e1',
            borderWidth: setBorderWidth,
          }
        }
      },
      { //不可修改
        value: angleOpen,
        cursor: 'default',
        itemStyle: {
          label: {
            show: false,
          },
          labelLine: {
            show: false,
          },
          color: 'rgba(0, 0, 0, 0)',
          borderColor: 'rgba(0, 0, 0, 0)',
          borderWidth: 0,
        }
      }
    ];

详细的解析在下面一起说,在这里就不说了,不然要说两遍。

四、ECharts实现第二种:

也不多说,先贴代码,下面在一起解析。和上面一样,分段来:

option = {
      // backgroundColor: '#04243E',
      title: {
        text: '体检信息',
      },
      series: [{
        name: '体检信息-底',
        type: 'pie',
        radius: ['69.5%', '70%'], //饼图的内外半径
        center: ['50%', '50%'], //圆心坐标
        avoidLabelOverlap: false, //是否启用防止标签重叠策略  默认true
        startAngle: -129.2, //起始角度,支持范围[0, 360]。   默认90
        legendHoverLink: false, //是否启用图例 hover 时的联动高亮   默认true
        hoverAnimation: false, //是否开启 hover 在扇区上的放大动画效果  默认true
        clockwise: true, //饼图的扇区是否是顺时针排布   默认true
        label: {
          show: false,
        },
        emphasis: {
          color: '#d9f0e1',
          borderColor: '#d9f0e1',
          borderWidth: 5,
        },
        data: dataDisposeDown,
      }, {
        name: '体检信息-上',
        type: 'pie',
        radius: ['69.5%', '70%'], //饼图的内外半径
        center: ['50%', '50%'], //圆心坐标
        avoidLabelOverlap: false, //是否启用防止标签重叠策略  默认true
        startAngle: -129.2, //起始角度,支持范围[0, 360]。   默认90
        legendHoverLink: false, //是否启用图例 hover 时的联动高亮   默认true
        hoverAnimation: false, //是否开启 hover 在扇区上的放大动画效果  默认true
        clockwise: true, //饼图的扇区是否是顺时针排布   默认true
        label: {
          show: false,
        },
        emphasis: {
          color: '#d9f0e1',
          borderColor: '#d9f0e1',
          borderWidth: 5,
        },
        data: dataDisposeTop,
      }]
    };

上面是option,下面是重要的实现部分:

/*-----------------------参数设置--------------------------*/
var point = 62.5; //获得的分数,限定:(0,totalPoint)
var totalPoint = 100; //总分 假设100
/*-----------------------上面的环--------------------------*/
var dataDisposeTop = [{
      value: 78 * point / totalPoint,
      name: point,
      cursor: 'default',
      zlevel: 2,
      label: {
        show: true,
        position: 'center',
        formatter: [
          '{a|' + point + '}',
          '{b|得分}'
        ].join('\n'),
        rich: {
          a: {
            fontSize: 45,
            color: 'black',
            fontWeight: 'bolder',
          },
          b: {
            color: '#eaae4f',
            fontSize: 25,
            height: 80,
          },
        }
      },
      itemStyle: {
        normal: {
          color: '#40b66b',
          borderWidth: 5, //描边线宽
          borderColor: '#40b66b', //图形的描边颜色
        },
        emphasis: {
          color: '#40b66b',
          borderColor: '#40b66b',
          borderWidth: 5,
        },
      }
    }, { //不可修改
      value: '22',
      name: '隐藏的部分',
      itemStyle: {
        label: {
          show: false,
        },
        labelLine: {
          show: false,
        },
        color: 'rgba(0, 0, 0, 0)',
        borderColor: 'rgba(0, 0, 0, 0)',
        borderWidth: 0,
      }
    }];
/*-----------------------下面的环--------------------------*/
var dataDisposeDown = [{
        value: 78,
        name: '底色',
        cursor: 'default',
        itemStyle: {
          normal: {
            color: '#d9f0e1',
            borderWidth: 5, //描边线宽
            borderColor: '#d9f0e1', //图形的描边颜色
          },
          zlevel: -1,
          legendHoverLink: false,
          emphasis: {
            color: '#d9f0e1',
            borderColor: '#d9f0e1',
            borderWidth: 5,
          }
        }
      },
      { //不可修改
        value: '22',
        name: '隐藏的部分',
        itemStyle: {
          label: {
            show: false,
          },
          labelLine: {
            show: false,
          },
          color: 'rgba(0, 0, 0, 0)',
          borderColor: 'rgba(0, 0, 0, 0)',
          borderWidth: 0,
        }
      }
    ];

五、解析

首先解析分几个步骤来:

第一个:怎么实现圆环的两端是弧线?

其实弧线的实现很简单,最开始按照我们原来接触line图的习惯,第一个想到的就是smooth参数,也就是平滑度。而在pei里面的这个属性有两个:series[i]-pie.labelLine.smooth和series-pie.data.labelLine.smooth。所以我们可以先尝试这个属性。然后发现,其实这个属性是用来设置视觉引导线的平滑度的。所以并没有用。    然后进入正题:其实实现就是给他边框,没错就是这么简单,详细代码贴出来:给个描边就解决了,这是官网社区里面的大神教我的。链接给一个:

思路来源:http://gallery.echartsjs.com/editor.html?c=xHkCjtI1Bm

itemStyle: {
    normal: {
      color: '#40b66b',
      borderWidth: 5, //描边线宽
      borderColor: '#40b66b', //图形的描边颜色
    },
   emphasis: {
      color: '#40b66b',
      borderColor: '#40b66b',
      borderWidth: 5,
    },
  }

第二个:怎么让一段文字显示不同的样式?

请看这里:http://www.echartsjs.com/option.html#series-pie.label.rich

关键的就是laible下面的rich属性!详细的代码也给出来:

label: {
    show: true,
    position: 'center',
    formatter: [
      '{a|' + point + '}',
      '{b|得分}'
    ].join('\n'),
    rich: {
      a: {
        fontSize: 45,
        color: 'black',
        fontWeight: 'bolder',
      },
      b: {
        color: '#eaae4f',
        fontSize: 25,
        height: 80,
      },
    }
  },

第三点:如何保证下面最大的开口两边持平?并且开口大小自定义?

首先:先回答第二个小问题:给个参数提出来就好了啊!!!然后第一个小问题:用简单的计算就可以实现了啊!!

哈哈,在给出的第一部分的代码里面,有这么一行:

startAngle: (270 - angleOpen / 2),                //起始角度,支持范围[0, 360]。   默认90

angleOpen 是我们给的开口大小的参数,然后经过这个以后就可以得出正确的起始角度了。没啥说的。

第四点:隐藏给出的数据?

直接给代码,引用就好了,很简单。

{ //不可修改
    value: angleOpen,
    cursor: 'default',
    itemStyle: {
      label: {
        show: false,
      },
      labelLine: {
        show: false,
      },
      color: 'rgba(0, 0, 0, 0)',
      borderColor: 'rgba(0, 0, 0, 0)',
      borderWidth: 0,
    }
  }

到此就结束了。。。希望解决了上面bug的道友分享一下解决方案哈!~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值