Echarts人口金字塔
先看一下设计效果图,如下图;这里完全实现这个效果是不好实现的,个人觉得有两个难点,一个是Y轴的列标,还有就是渐变效果,尝试了一下没有成功,就打住了
然后看一下最终的效果图,虽然有点丑,理想和现实总是有差距的对吧,废话不多说,下面看看我实现的心路历程吧。
获取数据
数据来源也是自己获取的,在数据库表中,只存了用户的出生年月日,也就是说,我需要根据当前系统时间,和存在库表中的时间计算年龄,然后根据算出来的年龄和性别分组,得到count即可,以下是我使用mssql数据库的查询语句,需要查看的就是sql中的datediff()这个方法,百度一下很多说明的,没有什么难点,很简单理解的sql语句
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参数说明,凑出了最后的效果,话不多说,直接上代码
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的我来说又是一次小成长,在学习的路上,我一直是捡贝壳的小男孩。
这篇文章是由这个博客网站作者发布的