echarts饼图百分比不为100%

一、问题

由于需要兼容低版本ie,使用的echarts版本较低,为2.2.x。当前版本有饼图百分比不为100%的问题,如数据为如下:
[
{ name: ‘测试1’, value: 1 },
{ name: ‘测试2’, value: 1 },
{ name: ‘测试3’, value: 1 }
]
当前版本饼图计算的百分比均为33.33%,最新版本计算的百分比是33.34%、33.33%、33.33%。

二、解决方法

搜索了一些文章是说用了最大余数法,但是在外部使用插件时无法使用这个算法,又不能改数据。只能修改源码。

1.增加转为百分数方法

(是从最新版本的number.ts拷贝过来修改ts格式为js,并处理为UglifyJs支持的方法)
文件路径echarts/util/number.js
顶部引入zrUtil:

var zrUtil = require('zrenderjs/tool/util');

增加的方法:

    /**
     * 获取给定精度的数据,确保valueList中的百分比之和为1
     * 采用最大余数法
     * @param {number[]} valueList 所有数据的列表
     * @param {number} idx 数据的索引
     * @param {number} precision 精度
     * @return {number} 百分数
     */
    function getPercentWithPrecision(valueList, idx, precision) {
        if (!valueList[idx]) {
            return 0;
        }

        var sum = valueList.reduce(function (acc, val) {
            return acc + (isNaN(val) ? 0 : val);
        }, 0);
        if (sum === 0) {
            return 0;
        }

        var digits = Math.pow(10, precision);
        var votesPerQuota = zrUtil.map(valueList, function (val) {
            return (isNaN(val) ? 0 : val) / sum * digits * 100;
        });
        var targetSeats = digits * 100;

        var seats = zrUtil.map(votesPerQuota, function (votes) {
            // Assign automatic seats.
            return Math.floor(votes);
        });
        var currentSum = seats.reduce(function (acc, val) {
            return acc + val;
        }, 0);

        var remainder = zrUtil.map(votesPerQuota, function (votes, idx) {
            return votes - seats[idx];
        });

        // Has remainding votes.
        while (currentSum < targetSeats) {
            // Find next largest remainder.
            var max = -Infinity;//Number.NEGATIVE_INFINITY;
            var maxId = null;
            for (var i = 0, len = remainder.length; i < len; ++i) {
                if (remainder[i] > max) {
                    max = remainder[i];
                    maxId = i;
                }
            }

            // Add a vote to max remainder.
            ++seats[maxId];
            remainder[maxId] = 0;
            ++currentSum;
        }

        return seats[idx] / digits;
    }

最后增加抛出的方法

return {
	//...
	getPercentWithPrecision: getPercentWithPrecision
}

2.修改百分数计算值

文件路径:echarts/chart/pie.js
顶部引入转百分比方法

var getPercentWithPrecision = require('echarts/util/number').getPercentWithPrecision;

绘图时计算百分比修改

/**
 * 构建单个饼图
 *
 * @param {number} seriesIndex 系列索引
 */
_buildSinglePie: function (seriesIndex) {
	//...
	var percentPrecision = (serie.percentPrecision || serie.percentPrecision === 0) ? serie.percentPrecision : 2;//百分数精度(增加percentPrecision配置)
	//...
	for (var i = 0, l = data.length; i < l; i++) {
		//...
		var valueList = zrUtil.map(data, function(obj) {
            return obj.value
        });
        percent = getPercentWithPrecision(valueList, i, percentPrecision) / 100;//修改百分比赋值,调用新方法
        //...
        percent = (percent * 100).toFixed(percentPrecision);//百分数精度从配置取
	}
}

三、算法原理

根据小数精度,将每一项占总和的百分数扩大至整数,比如[100,100,100],第一项计算为3333.33333333,然后整数部分就是3333,将余数求出来就是0.33333333,然后3项做同样的操作,得到余数数组。
判断百分数整数之和是否为100*小数精度,如果小于100*小数精度说明最后的百分比之和会小于100%,否则没有问题直接返回即可。
若百分比之和小于100%:通过遍历余数数组找到最大的余数,说明这一项占比比其他2项更大,因此给这一项的百分数整数+1,就得到3334,最后的结果整数为[3334,3333,3333],然后将百分数整数转为百分数即[33.34,33.33,33.33]。

四、遇到的报错

from UglifyJs
Unexpected token: name (currentSum)

原因:map要用zrUtil中的map方法,因为map是es6的内容,UglifyJs不支持。
reduce可以直接用,es3就支持了。

from UglifyJs
Unexpected token: operator (>)

原因:使用了箭头函数,修改箭头函数为function匿名函数。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值