Echarts人口金字塔

Echarts 人口金字塔

先看一下设计效果图,如下图;这里完全实现这个效果是不好实现的,个人觉得有两个难点,一个是 Y 轴的列标,还有就是渐变效果,尝试了一下没有成功,就打住了
设计图人口金字塔
然后看一下最终的效果图,虽然有点丑,理想和现实总是有差距的对吧,废话不多说,下面看看我实现的心路历程吧。
实现金字塔

获取数据

数据来源也是自己获取的,在数据库表中,只存了用户的出生年月日,也就是说,我需要根据当前系统时间,和存在库表中的时间计算年龄,然后根据算出来的年龄和性别分组,得到 count 即可,以下是我使用 mssql 数据库的查询语句,需要查看的就是 sql 中的 datediff()这个方法,百度一下很多说明的,没有什么难点,很简单理解的 sql 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT sex,CASE when datediff(year,Birthday,getdate()) <= 19 then '20岁以内'when datediff(year,Birthday,getdate()) between 20 and 29 then '20-30'when datediff(year,Birthday,getdate()) between 30 and 39 then '30-40'when datediff(year,Birthday,getdate()) between 40 and 49 then '40-50'when datediff(year,Birthday,getdate()) between 50 and 59 then '50-60'when datediff(year,Birthday,getdate()) between 60 and 69 then '60-70'when datediff(year,Birthday,getdate()) between 70 and 79 then '70-80'when datediff(year,Birthday,getdate()) between 80 and 89 then '90-90'else '90岁以上' end as 年龄段,count(*) as 年龄段人数from User WHERE DeleteStatus = 0group byCASE when datediff(year,Birthday,getdate()) <= 19 then '20岁以内'when datediff(year,Birthday,getdate()) between 20 and 29 then '20-30'when datediff(year,Birthday,getdate()) between 30 and 39 then '30-40'when datediff(year,Birthday,getdate()) between 40 and 49 then '40-50'when datediff(year,Birthday,getdate()) between 50 and 59 then '50-60'when datediff(year,Birthday,getdate()) between 60 and 69 then '60-70'when datediff(year,Birthday,getdate()) between 70 and 79 then '70-80'when datediff(year,Birthday,getdate()) between 80 and 89 then '90-90'else '90岁以上' END,sex

优化后
select t1.ageLevel,t1.sex,count(0) amount from (
select case when age between 20 and 29 then '20-30'
when age between 30 and 39 then '30-40'
when age between 40 and 49 then '40-50'
when age between 50 and 59 then '50-60'
when age between 60 and 69 then '60-70'
when age between 70 and 79 then '70-80'
when age between 80 and 89 then '80-90'
else '90以上' end
as ageLevel,sex from (
select datediff(year,Birthday,getdate()) age,* from User
) t
) t1
group by t1.ageLevel,t1.sex
order by t1.sex,t1.ageLevel
前端 echarts 实现

我结合网上查找的实例,和官网的 api 参数说明,凑出了最后的效果,话不多说,直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
 ajaxFormData('@Url.Action("GetTalentsAgesGrade", "Home")', {},
                function (res) {
                    let data = res.Data;
                    for (var i = 0; i < data.length; i++) {
                        gendarGrade.push(data[i].name)
                        let temp = {
                            name: "",
                            value: ""
                        };

                        if (data[i].sex == "男") {
                            temp.name = data[i].name;
                            temp.value = -data[i].value;
                            maleList.push(temp)
                        } else {
                            temp.name = data[i].name;
                            temp.value = data[i].value;
                            femaleList.push(temp)
                        }
                        list.push(data[i].value);
                    }
                    list.sort(function (num1, num2) {
                        return num1 - num2;
                    })
                    let tempString = '1';
                    maxValue = eval(list[list.length - 1]);//取最大值
                    for (let i = 0; i <= maxValue.length - 1; i++) {
                        tempString += '0';
                    }
                   // maxValue = Math.ceil(maxValue / 100) * 100;//向上取整(比如346 取400)
                    maxValue = Math.ceil(maxValue / Number(tempString)) *
Number(tempString);//向上取整(比如346 取400)
                    gendarGrade = Array.from(new Set(gendarGrade));//目录去重
                        let mybarChart = echarts.init(document.getElementById('barContainer1'));
                        let option = {
                            title: {
                                show: false,
                                text: '人才男女比例结构图',
                            },
                            backgroundColor: '#fff',
                            tooltip: {
                                trigger: 'axis',
                                axisPointer: {            // 坐标轴指示器,坐标轴触发有效
                                    type: 'shadow'        // 默认为直线,可选为:'line' |
'shadow'
                                },
                                formatter: function (data) {
                                    let ttt = data[0].name;
                                    for (let i = 0; i < data.length; i++) {
                                        ttt += '<br/>' + data[i].seriesName + ':' +
(Math.abs(data[i].value))+'人';
                                    }
                                    return ttt;
                                }
                            },

                            legend: {//图例设置
                                data: ['男士', '女士'],
                                x: '2%',
                                y:'5%',                             
                            },
                            color: ['#2575fc', '#ff1493'],//颜色设置、
                            grid: {
                                x: '10%',
                                x2: '5%',
                                y: '18%',
                                y2:'14%'
                            },
                            xAxis: [
                                {
                                    type: 'value',
                                    mix: function () {
                                        let aa =-1 *  maxValue;
                                        return aa;
                                    },
                                    max: maxValue,
                                    axisLabel: {
                                        formatter: function (a) {
                                            return Math.abs(a);
                                        },
                                        color: '#7d7d7d',
                                        fontWeight:'11'
                                    },
                                    axisTick: { show: false },
                                    axisLine: {
                                        lineStyle: {
                                            color:'#d8d8d8',
                                        }
                                    },
                                    splitLine: {
                                        show: true
                                    },
                                    splitNumber: 100,
                                    minInterval: 80,
                                    maxInterval: 200,
                                    itemStyle: {
                                        normal: {//这里设置了没有效果,本来是尝试做渐变效果的
                                            color: new echarts.graphic.LinearGradient(
                                                //右 / 下 / 左 / 上
                                                1, 0, 0, 0,
                                                [
                                                    { offset: 0, color: '#2575fc' },
                                                    { offset: 0.5, color: '#2c6af6' },
                                                    { offset: 1, color: '#6a11cb' }
                                                ]
                                            )
                                        }                               
                                    }
                                }
                            ],
                            yAxis: [
                                {
                                    type: 'category',
                                    nameLocation: "middle",
                                     axisTick: { show: false },
                                     data: gendarGrade,
                                     axisLabel: {                                      
                                         color: '#1d1d1b',
                                         fontWeight: '11'
                                     },
                                }
                            ],
                            series: [
                                {
                                    name: '男士',
                                    type: 'bar',
                                    stack: '总量',
                                    barWidth:'50%',
                                    data: maleList
                                },
                                {
                                    name: '女士',
                                    type: 'bar',
                                    stack: '总量',
                                    barWidth: '50%',
                                    data: femaleList
                                }
                            ]
                        };
                         mybarChart.setOption(option);
                });

最后简单总结下前端实现的思路,其实就是一个柱状图的实现,让其分组结果左右显示,最重要的是左边,我让其 value 全部为负数了,这样就能显示在左边了,最后鼠标移入和图形显示为什么不是负数呢,建议看一下 tooltip.formatter()和 xAxis.formatter()这里的重写方法,echarts 的官方说明文档是有详细说明的。最后比较坑的点是,如果左右最大值不一样的话,y 轴就没在整个图的中间,这里我的解决办法,是 xAxis.max 设置的值是,这两组数据的最大值。
我做的还原度不是很好,但对没接触过 echarts 的我来说又是一次小成长,在学习的路上,我一直是捡贝壳的小男孩。

您的打赏,是我创作的动力,谢谢支持。
0%