echats柱状图\折线图:数量级自动调整;动态设置多维度

通过构造echarts返回体EchartsData.class,在返回体内开发功能代码,实现echarts数据的改动。

特点:
1、y轴数据的数量级自动调整,使图表变化趋势更明显;
2、支持多维度数据【可以有1-N多个维度】

// EchartsData对象构造样例代码
List<String> xAxis = Arrays.asList("鲤鱼","草鱼","三文鱼","鳕鱼","龙利鱼","鲫鱼");
List<Object> barList = Arrays.asList("12345","2345","3456","4567","67891","7891");

final EchartsData echartsData = new EchartsData("新增情况图表", xAxis).setFirstYAxis("总数", barList);
echartsData.setLineYAxis(“利用率(%)”, line1List);
// echartsData.setLineYAxis(“利用率_2”, line2List);
// ...
// echartsData.setLineYAxis(“利用率_N”, lineNList);

在这里插入图片描述

xxx
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.Getter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * echarts 表格数据结构体
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter // 规定了“不同图标类型的y坐标值”与y坐标系维度列表的对应关系,故不允许随意set
public class EchartsData extends HashMap<String, Object> {

    /**
     * 标题
     */
    private final String title;
    /**
     * 横坐标值
     */
    private final List<String> xAxis;
    /**
     * 多维纵坐标的维度名称列表
     * 按索引号,分别对应坐标值:barList、line1List、line2List
     * 若对应的坐标值列表List为空,则表示无数据
     */
    private List<String> yAxisDimensionNameList;

    /**
     * 柱状图-纵坐标值
     * 元素可能为简单数据类型,
     * 也可能为DataWithItemStyleVO.class类型,用于标识该值的显示样式
     */
    private List<Object> barList; // 柱状图
//    private List<String> line{0}List; // 折线图

    public EchartsData(String title, List<String> xAxis) {
        this.title = title;
        this.xAxis = xAxis;
        this.yAxisDimensionNameList = new ArrayList<>();
        // map对象,使用MapSerializer解析时,不会序列自身的属性
        put("title", this.title);
        put("xAxis", this.xAxis);
        put("yAxisDimensionNameList", this.yAxisDimensionNameList);
    }

    public EchartsData setFirstYAxis(String dimension, List<?> barList) {
        ParamException.isTrue(StringUtils.isBlank(dimension), "inputParam[dimension] should not be blank");
        if (CollectionUtils.isEmpty(barList)) {
            return this;
        }
        YAxis yAxis = balanceNum(dimension, barList);
        yAxisDimensionNameList.add(yAxis.getDimension());
        this.barList = yAxis.getDataList();
        put("barList", this.barList);
        return this;
    }

    public EchartsData setLineYAxis(String dimension, List<String> lineList) {
        ParamException.isTrue(StringUtils.isBlank(dimension), "inputParam[dimension] should not be blank");
        if (CollectionUtils.isEmpty(lineList)) {
            return this;
        }
        YAxis yAxis = balanceNum(dimension, lineList); // 不指定索引号add,避免覆盖原有元素
        yAxisDimensionNameList.add(yAxis.getDimension());
        int index = yAxisDimensionNameList.size() - 1;
        final String key = MessageFormat.format("line{0}List", index);
        put(key, yAxis.getDataList());
        return this;
    }

    private YAxis balanceNum(String sourceDimension, List<?> sourceList) {
        List<Object> targetList;
        String targetDimension;
        List<BigDecimal> tempNumList = new ArrayList<>();
        sourceList.forEach(data -> {
            String value;
            if (data instanceof DataWithItemStyleVO) {
                value = ((DataWithItemStyleVO) data).getValue();
            } else {
                value = String.valueOf(data);
            }
            // 非数字会报错
            final BigDecimal dNum = NumberUtil.parseStrToBigDecimal(value);

            tempNumList.add(dNum);
        });
        tempNumList.sort(BigDecimal::compareTo);
        final BigDecimal min = tempNumList.get(0);
        final int minLength = String.valueOf(min.intValue()).length();
        final BigDecimal max = tempNumList.get(tempNumList.size() - 1);
        final int maxLength = String.valueOf(max.intValue()).length();
        // 是否进行数值大小转换
        if (!sourceDimension.contains("率") // 为了避免调整百分数,双保险(部分字段的百分数值,没有带百分号。若数值本身的带百分号的minLength=1不会转换)。若是转化,单位会很奇怪,又是百分号、又是数量单位。
                && maxLength >= minLength
                //  不可自动调整的数据如(为了避免调整百分数):88 vs 10; 987 vs 10; 101 vs 99
                && (minLength > 2 || (minLength > 1 && (maxLength - minLength) > 1)) // 如:880 vs 100; 8800 vs 10
        ) {
            targetList = new ArrayList<>();
            // 将最小值,处理成个位数。缩短无用y轴刻度,使y轴数值差异明显化
            // 若存在负数、小数:存在小数-因为整数位数为0故不会进行转化;存在负数-要求最小值即负数的位数比正数最大值位数短即可(否则转换后正数会小于0不符合所有值绝对值都大于零的预期)。
            int powerOfTen = minLength - 1;
            BigDecimal divisor = BigDecimal.valueOf(10).pow(powerOfTen); // 10的n次方。使得最小值为个位数
            for (int i = 0; i < sourceList.size(); i++) { // 不打乱原排序
                Object data = sourceList.get(i);
                DataWithItemStyleVO dataWithItemStyleVO = null;
                String value;
                if (data instanceof DataWithItemStyleVO) {
                    dataWithItemStyleVO = (DataWithItemStyleVO) data;
                    value = dataWithItemStyleVO.getValue();
                } else {
                    value = String.valueOf(data);
                }
                final BigDecimal dNum = NumberUtil.parseStrToBigDecimal(value);
                final BigDecimal divide = dNum.divide(divisor);
                if (Objects.isNull(dataWithItemStyleVO)) {
                    targetList.add(divide.toString());
                } else {
                    targetList.add(new DataWithItemStyleVO(divide.toString(), dataWithItemStyleVO.getItemStyle()));
                }
            }

            // 追加转换后的单位
            NumCountUnitEnum unitEnum = NumCountUnitEnum.valueOf(powerOfTen);
            targetDimension = MessageFormat.format("{0}({1})", sourceDimension, unitEnum.getCountUnitName()); // 中文括号前端无法识别

        } else {
            // 数值小于1000,不做处理
            targetList = sourceList.stream().map(data -> (Object) data).collect(Collectors.toList());
            targetDimension = sourceDimension;
        }
        YAxis yaxis = new YAxis();
        yaxis.setDataList(targetList);
        yaxis.setDimension(targetDimension);
        return yaxis;
    }


    enum NumCountUnitEnum {
        ONE(0, "个"),
        TWO(1, "十"),
        THREE(2, "百"),
        FOUR(3, "千"),
        FIVE(4, "万"),
        SIX(5, "十万"),
        SEVEN(6, "百万"),
        EIGHT(7, "千万"),
        NINE(8, "亿"),
        ;

        /**
         * 10的幂次
         */
        private Integer powerOfTen;

        /**
         * 计数单位中文名
         */
        private String countUnitName;

        NumCountUnitEnum(Integer powerOfTen, String countUnitName) {
            this.powerOfTen = powerOfTen;
            this.countUnitName = countUnitName;
        }

        public static NumCountUnitEnum valueOf(Integer powerOfTen) {
            ParamException.isTrue(Objects.isNull(powerOfTen), "invalid null powerOfTen");
            for (NumCountUnitEnum elem : values()) {
                if (powerOfTen.equals(elem.powerOfTen)) {
                    return elem;
                }
            }
            throw new ParamException(String.format("invalid powerOfTen: [%s]", powerOfTen));
        }

        public Integer getPowerOfTen() {
            return powerOfTen;
        }

        public String getCountUnitName() {
            return countUnitName;
        }
    }

    @Data
    class YAxis {
        private String dimension;

        private List<Object> dataList;
    }
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Echarts 柱状图上显示折线,可以通过使用 Echarts 的组合图表来实现。具体步骤如下: 1. 首先,确保你已经引入了 EchartsJavaScript 文件。 2. 创建一个包含柱状图折线图的容器元素,例如一个 `<div>` 元素。 3. 使用 Echarts 的 `echarts.init` 方法初始化图表,并将容器元素传递给该方法。 4. 定义柱状图的配置项,包括数据、样式等。 5. 定义折线图的配置项,包括数据、样式等。 6. 将柱状图折线图的配置项分别传递给 `echarts.init` 方法创建的实例。 7. 使用 `setOption` 方法将柱状图折线图的配置项设置图表中。 示例代码如下所示: ```javascript // 创建图表容器 var chartContainer = document.getElementById('chart'); // 初始化图表 var chart = echarts.init(chartContainer); // 定义柱状图配置项 var barOption = { // 柱状图数据 series: [{ type: 'bar', data: [10, 20, 30, 40, 50] }] }; // 定义折线图配置项 var lineOption = { // 折线图数据 series: [{ type: 'line', data: [5, 10, 15, 20, 25] }] }; // 设置柱状图折线图的配置项 chart.setOption(barOption); chart.setOption(lineOption); ``` 可以根据自己的需求调整柱状图折线图的样式、数据等。记得在 HTML 中创建一个容器元素,并给它一个唯一的 ID,然后将该 ID 传递给 `document.getElementById` 方法来获取容器元素的引用。 注意:以上代码仅为示例,实际开发中可能需要根据实际情况进行适当的修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值