ECharts柱状图

1.小节概述

    上小节中,我们搭建了Vue(2.x)项目并集成了ECharts(5.4.3)、Axios(1.4.0),从这节开始将通过完善项目来了解ECharts中各类图表的具体用法。ECharts本身功能比较强悍,建议在实际业务开发中遇到问题时多查阅官网文档,尤其是配置项手册、API、示例等内容。在本小节和后续专栏章节中,并非逐个学习了解官方文档的各个配置项或API,而是直接根据业务场景中的小需求点来熟悉ECharts图表的常用配置。

    柱状图一般指柱形图,又称长条图、柱状统计图、条图、条状图、棒形图,是一种以长方形的长度为变量的统计图表,主要是用来反映对比数据之间的关系,也可以用来反应数据的变化趋势等。在本小节中,主要记录ECharts柱状图的基础设置,结合实际业务场景实现双柱图、堆叠柱图、动态排序柱状图、阶梯瀑布图等图表展现。

2.操作步骤

2.1.基础设置

1.以上小节最后得到的分公司销售量柱状图为例,首先调整下图例的设置,包括图例位置、图标类型、字体颜色大小等。图例展现了不同系列的标记,颜色和名字,可以通过点击图例控制哪些系列显示或者不显示。参考代码:

legend: {
    show: true,
    data: ["销量"],
    icon: "roundRect",
    x: "center",
    y: "bottom",
    padding: [0, 0, 10, 0],
    textStyle: {
        fontStyle: "normal",
        fontSize: 12,
    },
},

2.可以看到上图的图形位置感觉有点不正,可以通过绘图网格grid相关属性来调整图表离容器的距离样式,可以通过调整grid组件离容器上下左右的距离来控制图表位置(参数可以是具体像素值或百分比,后续随着图表元素的增多此处可以根据实际情况调整边距)。另外需要注意containLabel参数(grid区域是否包含坐标轴的刻度标签),有时为了防止标签溢出此处设置为true(算边距时带上刻度标签以防溢出容器或者覆盖其他组件)。参考代码:

grid: {
    top: '8%',
    bottom: '10%',
    left: '2%',
    right: '8%',
    containLabel: true
},

3.提示框的内容设置(鼠标滑过或点击图表时的显示框),包括提示框内容字体颜色大小、提示框显示样式格式化等。参考代码:

tooltip: {
    show: true,
    textStyle: {
        color: "#000000",
        fontStyle: "normal",
        fontSize: 14,
        align: "left",
    },
    formatter: function (param) {
        let message = "分公司:" + param.name + "<br />" + "销量:" + param.data;
        return message;
    },
},

 

4.坐标轴设置:x轴和y轴。

[1] 设置x轴和y轴刻度线、分割线、坐标轴轴线和箭头等样式内容。参考代码:

xAxis: {
    type: 'category',
    data: chartData.data.dept,
    axisLine: {
        // 坐标轴轴线
        show: true,
        // 只在末端显示箭头
        symbol: ['none', 'arrow'],
        // 箭头大小和位置
        symbolSize: [6, 6],
        symbolOffset: [0, 6],
    },
    axisTick: {
        // 刻度线设置
        show: true,
        alignWithLabel: true,
    },
    axisLabel: {
        show: true,
        interval: 0,
    },
    splitLine: {
        show: false,
    },
},

yAxis: {
    type: 'value',
    name: '件',
    axisLine: {
        show: true,
        symbol: ['none', 'arrow'],
        symbolSize: [6, 6],
        symbolOffset: [0, 6],
    },
    axisTick: {
        show: false,
        alignWithLabel: true,
    },
    splitLine: {
        // 分隔线设置
        show: true,
        lineStyle: {
            color: ['#E5EAF3'],
            width: 1,
            type: 'dashed',
        },
    },
},

[2] 设置x轴横坐标:有时候横坐标值显示的字太多稍显拥挤甚至自动隐藏掉了,那么能否设置为倾斜显示。参考代码:

xAxis: {
    axisLabel: {
        show: true,
        interval: 0,
        rotate: 45,
    },
},

[3] 设置x轴横坐标:既然横坐标值能倾斜显示,那么能否设置为竖排显示。参考代码:

axisLabel: {
    show: true,
    interval: 0,
    // rotate: 45,
    formatter: function (value) {
        return value.split('').join('\n')
    },
},

5.配置图表系列(series)。

[1] 为了方便记录,按照上小节搭建项目时的步骤,新建组件ChartBarTwo.vue(可以通过复制ChartBarOne快速创建),并引入到Home页图表2的位置上。设置柱子宽度,柱子圆角显示,设置柱子颜色和值显示到柱子上。参考代码:

series: [
    {
        name: '销量',
        type: 'bar',
        data: chartData.data.salesAmount,
        // 设置柱子宽度
        barWidth: 55,
        label: {
            // 值显示到柱子上
            show: true,
            position: 'top',
            fontSize: 10,
        },
        itemStyle: {
            // 顺时针设置圆角:左上、右上、右下、左下
            borderRadius: [8, 8, 0, 0],
            // 柱子颜色设置方式1:批量设置柱子颜色
            color: '#F43368',
        },
    },
],

[2] 给不同的柱子设置不同的颜色。参考代码:

series: [
    {
        itemStyle: {
            // 顺时针设置圆角:左上、右上、右下、左下
            borderRadius: [8, 8, 0, 0],
            // 柱子颜色设置方式2:给不同的柱子加不同颜色
            color: function (params) {
                let colorList = ["#5470C6","#91CC75","#FAC858","#EE6666","#73C0DE"];
                return colorList[params.dataIndex];
            },
        },
    },
],

[3] 根据值的情况给柱子设置不同的颜色,例如销量超过8000显示蓝色,销售超过5000低于8000显示黄色,销量低于5000显示红色。参考代码:

series: [
    {
        itemStyle: {
            // 顺时针设置圆角:左上、右上、右下、左下
            borderRadius: [8, 8, 0, 0],
            // 柱子颜色设置方式3:根据值的情况设置不同颜色
            color: function (params) {
                let colorList = ["#5470C6", "#FAC858", "#EE6666"];
                let amount = params.data;
                if (amount >= 8000) {
                    return colorList[0];
                } else if (amount < 8000 && amount >= 5000) {
                    return colorList[1];
                } else {
                    return colorList[2];
                }
            },
        },
    },
],

[4] 标记最大值、最小值和平均值。参考代码:

grid: {
    top: '14%',
    bottom: '10%',
    left: '2%',
    right: '10%',
    containLabel: true,
},
series: [
    {
        label: {
            show: true,
            position: 'inside',
            fontSize: 10,
        },
        markPoint: {
            data: [
                {
                    type: "max",
                    name: "最大值",
                    symbol: "pin",
                    itemStyle: {color: '#5470C6'}
                },
                {
                    type: "min",
                    name: "最小值",
                    symbol: "pin",
                    itemStyle: {color: '#EE6666'}
                },
            ],
        },
        markLine: {
            data: [
                {
                    type: "average",
                    name: "平均值",
                },
            ],
        },
    },
],

6.至此,基础设置相关介绍告一段落,启动项目,预览Home页如下图:

2.2.双柱图和堆叠图

1.准备工作:假设要展示的各分公司销量包括两大产品的销售-牛奶和面包,那么可以用双柱图来展示。修改前端前需要再加一个后端接口(RAP接口管理平台中新建接口提供分公司牛奶和面包的产品销量),然后复制出一个的图表组件ChartBarThree.vue放在Home页图表3的位置上进行展示。

2.请求接口数据,配置series,实现双柱显示(即显示多个系列的柱子)。参考代码:

// 请求数据回来
async getChartData() {
    this.chartData = await this.$axios({ url: 'sales/product' })
},

// 部分echarts配置项信息
legend: {
    show: true,
    x: "center",
    y: "bottom",
    padding: [0, 0, 10, 0],
},
series: [
    {
        name: '面包',
        type: 'bar',
        data: chartData.data.breadAmount,
        itemStyle: {
            // 顺时针设置圆角:左上、右上、右下、左下
            borderRadius: [6, 6, 0, 0],
            // 设置柱子颜色
            color: '#5470C6',
        },
    },
    {
        name: '牛奶',
        type: 'bar',
        data: chartData.data.milkAmount,
        itemStyle: {
            // 顺时针设置圆角:左上、右上、右下、左下
            borderRadius: [6, 6, 0, 0],
            // 设置柱子颜色
            color: '#91CC75',
        },
    },
],

3.既然已经展示了多条柱子,能否进行堆叠展示,并且希望顶部显示出来合计值。其实只需要给各个图例添加相同的stack属性便于实现,合计值的实现是在最后一个图例上显示值并进行格式化处理。参考代码:

series: [
    {
        name: '面包',
        type: 'bar',
        stack: '销量',
        data: chartData.data.breadAmount,
        itemStyle: {
            // 顺时针设置圆角:左上、右上、右下、左下
            borderRadius: [6, 6, 0, 0],
            // 设置柱子颜色
            color: '#5470C6',
        },
    },
    {
        name: '牛奶',
        type: 'bar',
        stack: '销量',
        data: chartData.data.milkAmount,
        itemStyle: {
            // 顺时针设置圆角:左上、右上、右下、左下
            borderRadius: [6, 6, 6, 6],
            // 设置柱子颜色
            color: '#91CC75',
        },
        label: {
            show: true,
            position: 'top',
            fontSize: 10,
            formatter: function (params) {
                return params.data + chartData.data.breadAmount[params.dataIndex]
            },
        },
    },
],

4.至此,双柱和堆叠相关介绍告一段落,启动项目,预览Home页如下图:

2.3.动态排序柱状图

1.动态排序柱状图是一种展示随时间变化的数据排名变化的图表。准备工作:假设要展示的各分公司上半年累计销量排名情况,那么可以用动态排序柱状图来展示。修改前端前需要再加一个后端接口(RAP接口管理平台中新建接口提供上半年销量数据),然后复制出一个的图表组件ChartBarFour.vue放在Home页图表4的位置上进行展示。

2.在ChartBarFour.vue组件中实现动态排序柱状图,具体实现要点包括:[1] 动态排序柱状图通常是横向的柱条,如果想要采用纵向的柱条,可以把x轴和y轴相反设置即可。[2] 在option中,设置series.realtimeSort、xAxis.max、yAxis.inverse、yAxis.animationDuration、animationDuration、animationDurationUpdate等参数。[3] 以 animationDurationUpdate 的频率调用 setInterval,更新数据值,显示下一个时间点对应的柱条排序。参考代码:

<template>
    <div class="mainDiv">
        <div class="titleDiv">上半年累计销量</div>
        <div class="chartDiv" id="chartBarFour"></div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            chartData: {},
            saleAmountArray: {},
            currentIndex: 0,
            currentMonth: '2023.01',
        }
    },
    name: 'ChartBarFour',
    mounted() {
        this.getChartData().then(() => {
            let myChart = this.$echarts.init(document.getElementById('chartBarFour'))
            // 数据请求到后渲染图表
            this.renderChart(myChart)
            // 更新图表option
            let that = this
            setInterval(function () {
                that.update(myChart)
            }, 3000)
        })
    },
    methods: {
        // 请求数据回来
        async getChartData() {
            this.chartData = await this.$axios({ url: '/sales/halfYear' })
            this.saleAmountArray = this.chartData.data.salesAmount
        },
        // 渲染图表
        renderChart(myChart) {
            let chartData = this.chartData
            let saleAmountArray = this.saleAmountArray
            let index = this.currentIndex
            var option = {
                grid: {
                    top: '8%',
                    bottom: '5%',
                    left: '2%',
                    right: '12%',
                    containLabel: true,
                },
                xAxis: {
                    max: 'dataMax',
                },
                yAxis: {
                    type: 'category',
                    data: chartData.data.dept,
                    inverse: true,
                    animationDuration: 300,
                    animationDurationUpdate: 300,
                    max: 7,
                },
                series: [
                    {
                        realtimeSort: true,
                        name: '销量',
                        type: 'bar',
                        data: saleAmountArray[index].value,
                        label: {
                            show: true,
                            position: 'right',
                            valueAnimation: true,
                        },
                        itemStyle: {
                            // 顺时针设置圆角:左上、右上、右下、左下
                            borderRadius: [0, 8, 8, 0],
                            // 柱子颜色设置方式3:根据值的情况设置不同颜色
                            color: function (params) {
                                let colorList = ['#5470C6', '#FAC858', '#EE6666']
                                let amount = params.data
                                if (amount >= 6000) {
                                    return colorList[0]
                                } else if (amount < 6000 && amount >= 4000) {
                                    return colorList[1]
                                } else {
                                    return colorList[2]
                                }
                            },
                        },
                    },
                ],
                animationDuration: 3000,
                animationDurationUpdate: 3000,
                animationEasing: 'linear',
                animationEasingUpdate: 'linear',
                graphic: {
                    elements: [
                        {
                            type: 'text',
                            right: 20,
                            top: 0,
                            style: {
                                text: '2023.01',
                                font: 'bolder 20px monospace',
                                fill: 'rgba(100, 100, 100, 0.6)',
                            },
                            z: 100,
                        },
                    ],
                },
            }
            // 使用刚指定的配置项和数据显示图表
            myChart.setOption(option)
        },
        // 更新图表option
        update(myChart) {
            // 半年度数据动态增长
            if (this.currentIndex < 5) {
                this.currentIndex = this.currentIndex + 1
            } else {
                this.currentIndex = 0
            }
            let saleAmountArray = this.saleAmountArray
            let index = this.currentIndex
            var newOption = {
                series: [
                    {
                        data: saleAmountArray[index].value,
                    },
                ],
                graphic: {
                    elements: [
                        {
                            type: 'text',
                            right: 20,
                            top: 0,
                            style: {
                                text: saleAmountArray[index].month,
                                font: 'bolder 20px monospace',
                                fill: 'rgba(100, 100, 100, 0.6)',
                            },
                            z: 100,
                        },
                    ],
                },
            }
            myChart.setOption(newOption)
        },
    },
}
</script>

<style scoped>
.mainDiv {
    border: 1px solid;
    height: 410px;
    border-radius: 5px;
    text-align: center;
}
.titleDiv {
    height: 30px;
    line-height: 30px;
    font-size: 12;
}
.chartDiv {
    height: 380px;
}
</style>

3.至此,动态排序柱状图相关介绍告一段落,启动项目,预览Home页如下图:

2.4.瀑布柱状图

1.瀑布图通过巧妙的设置,使图表中数据的排列形状(称为浮动列)看似瀑布悬空,从而反映数据在不同时期或受不同因素影响的程度及结果,还可以直观反映出数据的增减变化,常见的有瀑布柱状图和阶梯瀑布图。

2.瀑布柱状图主要反应数据的构成,例如展示当月收入来源情况。准备工作:修改前端前需要再加一个后端接口(RAP接口管理平台中新建接口提供当月收入来源数据),然后复制出一个的图表组件ChartBarFive.vue放在Home页图表5的位置上进行展示。

3.在ChartBarFive.vue组件中实现瀑布柱状图,实际上实现原理和堆叠柱状图是一样的,只不过通过柱状颜色把一些堆叠柱子隐藏掉了,这样看来就像瀑布一样,飞流直下。参考代码:

<template>
    <div class="mainDiv">
        <div class="titleDiv">当月收入来源情况</div>
        <div class="chartDiv" id="chartBarFive"></div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            chartData: {},
        }
    },
    name: 'ChartBarFive',
    mounted() {
        this.getChartData().then(() => {
            // 数据请求到后渲染图表
            this.renderChart()
        })
    },
    methods: {
        // 请求数据回来
        async getChartData() {
            this.chartData = await this.$axios({ url: 'income' })
        },
        // 渲染图表
        renderChart() {
            let myChart = this.$echarts.init(document.getElementById('chartBarFive'))
            let chartData = this.chartData
            var option = {
                tooltip: {
                    show: true,
                },
                grid: {
                    top: '5%',
                    bottom: '5%',
                    left: '2%',
                    right: '8%',
                    containLabel: true,
                },
                xAxis: {
                    type: 'category',
                    data: chartData.data.type,
                    axisTick: {
                        // 刻度线设置
                        show: true,
                        alignWithLabel: true,
                    },
                    splitLine: {
                        show: false,
                    },
                },

                yAxis: {
                    type: 'value',
                },
                series: [
                    {
                        name: '占位',
                        type: 'bar',
                        stack: '收入',
                        itemStyle: {
                            borderColor: 'transparent',
                            color: 'transparent',
                        },
                        emphasis: {
                            itemStyle: {
                                borderColor: 'transparent',
                                color: 'transparent',
                            },
                        },
                        data: chartData.data.placeholder,
                    },
                    {
                        name: '收入',
                        type: 'bar',
                        stack: '收入',
                        label: {
                            show: true,
                            position: 'inside',
                        },
                        itemStyle: {
                            color: function (params) {
                                if(params.name == '合计'){
                                    return '#91CC75'
                                }else{
                                    return '#5470C6'
                                }  
                            }
                        },
                        data: chartData.data.income,
                    },
                ],
            }
            // 使用刚指定的配置项和数据显示图表
            myChart.setOption(option)
        },
    },
}
</script>

<style scoped>
.mainDiv {
    border: 1px solid;
    height: 410px;
    border-radius: 5px;
    text-align: center;
}
.titleDiv {
    height: 30px;
    line-height: 30px;
    font-size: 12;
}
.chartDiv {
    height: 380px;
}
</style>

4.阶梯瀑布图可以展示出某个时间段线上某些值的增减情况,例如展示当月收入支出情况。准备工作:修改前端前需要再加一个后端接口(RAP接口管理平台中新建接口提供当月收入支出数据),然后复制出一个的图表组件ChartBarSix.vue放在Home页图表6的位置上进行展示。

5.在ChartBarSix.vue组件中实现阶梯瀑布图,相比瀑布柱状图,此处相当于进行三柱堆叠处理。参考代码:

<template>
    <div class="mainDiv">
        <div class="titleDiv">当月收入支出情况</div>
        <div class="chartDiv" id="chartBarSix"></div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            chartData: {},
        }
    },
    name: 'ChartBarFive',
    mounted() {
        this.getChartData().then(() => {
            // 数据请求到后渲染图表
            this.renderChart()
        })
    },
    methods: {
        // 请求数据回来
        async getChartData() {
            this.chartData = await this.$axios({ url: 'income/expense' })
        },
        // 渲染图表
        renderChart() {
            let myChart = this.$echarts.init(document.getElementById('chartBarSix'))
            let chartData = this.chartData
            var option = {
                tooltip: {
                    show: true,
                },
                grid: {
                    top: '5%',
                    bottom: '5%',
                    left: '2%',
                    right: '8%',
                    containLabel: true,
                },
                xAxis: {
                    type: 'category',
                    data: chartData.data.type,
                    axisTick: {
                        // 刻度线设置
                        show: true,
                        alignWithLabel: true,
                    },
                    splitLine: {
                        show: false,
                    },
                },

                yAxis: {
                    type: 'value',
                },
                series: [
                    {
                        name: '占位',
                        type: 'bar',
                        stack: '收支',
                        itemStyle: {
                            borderColor: 'transparent',
                            color: 'transparent',
                        },
                        emphasis: {
                            itemStyle: {
                                borderColor: 'transparent',
                                color: 'transparent',
                            },
                        },
                        data: chartData.data.placeholder,
                    },
                    {
                        name: '收入',
                        type: 'bar',
                        stack: '收支',
                        label: {
                            show: true,
                            position: 'inside',
                            fontSize: 10,
                        },
                        itemStyle: {
                            color: function (params) {
                                if (params.name == '合计') {
                                    return '#91CC75'
                                } else {
                                    return '#5470C6'
                                }
                            },
                        },
                        data: chartData.data.income,
                    },
                    {
                        name: '支出',
                        type: 'bar',
                        stack: '收支',
                        label: {
                            show: true,
                            position: 'inside',
                            fontSize: 10,
                        },
                        itemStyle: {
                            color: '#F43368',
                        },
                        data: chartData.data.expense,
                    },
                ],
            }
            // 使用刚指定的配置项和数据显示图表
            myChart.setOption(option)
        },
    },
}
</script>

<style scoped>
.mainDiv {
    border: 1px solid;
    height: 410px;
    border-radius: 5px;
    text-align: center;
}
.titleDiv {
    height: 30px;
    line-height: 30px;
    font-size: 12;
}
.chartDiv {
    height: 380px;
}
</style>

 6.至此,瀑布图相关介绍告一段落,启动项目,预览Home页如下图:

3.小节总结

    柱状图最适合对分类的数据进行比较,尤其是当数值比较接近时,由于人眼对于高度的感知优于其他视觉元素(如面积、角度等),因此使用柱状图更加合适。本小节主要记录了ECharts柱状图的基础设置,并延伸介绍了如何实现双柱图、堆叠柱图、动态排序柱状图、瀑布柱状图、阶梯瀑布图等可视化图表。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值