为了冲个官方认证新星博主,发点库存
在地理坐标系中镶嵌柱状图,在加上时间轴让图动起来
将现成的内容加以组合,一直是白嫖的最高级形式。对此,PPAP大叔直呼内行。
echarts,作为一款基于JavaScript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表,深受开发者的青睐。对于追求极致可视化效果的小伙伴们来说,echarts官网上的示例项目虽然好看,但是部分图表类型用多了之后不免显得比较单调。有没有可能把各种图表、组件组合起来呢,比如:
答案是肯定的,废话不多说,直接上效果:
这是我之前做的一个项目当中的效果,【图中各指标具体值均可交互式点击查看】,需求方要求这个图中尽可能直观地显示若干年来,长沙市若干观测点的各空气指标观测结果情况,要求既有时间上的横向比较,又要有空间上的纵向比较。
重点代码:
var geoCoordMap = {
"高开区环保局": [112.899413, 28.222028],
"湖南师范大学": [112.95596, 28.193113],
"湖南中医药大学": [112.900747, 28.135339],
"长沙火车新站": [113.073925, 28.153638],
"经开区环保局": [113.09324, 28.256078],
"马坡岭": [113.084348, 28.207655],
"沙坪": [113.02943, 28.360665],
"天心区环保局": [112.996422, 28.11997],
"伍家岭": [113.000184, 28.236678],
"雨花区环保局": [113.043174, 28.1304],
};
//图表数据
var rawData = [{
"name": "高开区环保局",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "湖南师范大学",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "湖南中医药大学",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "长沙火车新站",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "经开区环保局",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "马坡岭",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "沙坪",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "天心区环保局",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "伍家岭",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}, {
"name": "雨花区环保局",
"PM25": 0,
"PM10": 0,
"O3": 0,
"NO2": 0,
"SO2": 0,
"CO": 0
}];
var rawDatas = rawData
var yearList = ['2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021']
//地图上显示饼图
function renderEachCity() {
//图表设置
mapOption = {
xAxis: [],
yAxis: [],
grid: [],
series: []
};
//循环数据
echarts.util.each(rawData, function (dataItem, idx) {
//饼图位置
var itemCenter = geoCoordMap[dataItem.name];
var geoCoord = [];
geoCoord.push(itemCenter[0]);
geoCoord.push(itemCenter[1]);
var coord = myChart.convertToPixel('geo', geoCoord);
idx += '';
//饼图数据
var datalist = [];
datalist.push(
dataItem.PM25,
dataItem.PM10,
dataItem.O3,
dataItem.NO2,
dataItem.SO2,
dataItem.CO
);
//图表设置
mapOption.xAxis.push({
id: idx,
gridId: idx,
type: 'category',
name: dataItem.name,
nameLocation: 'middle',
nameGap: 3,
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
axisLine: {
onZero: false,
lineStyle: {
color: '#666'
}
},
data: ['PM2.5', 'PM10', 'O3', 'NO2', 'SO3', 'CO'],
z: 100
});
mapOption.yAxis.push({
id: idx,
gridId: idx,
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
axisLine: {
show: false,
lineStyle: {
color: '#1C70B6'
}
},
z: 100
});
mapOption.grid.push({
id: idx,
width: 30,
height: 40,
left: coord[0] - 15,
top: coord[1] - 15,
z: 100
});
mapOption.series.push({
id: idx,
type: 'bar',
xAxisId: idx,
yAxisId: idx,
barGap: 0,
barCategoryGap: 0,
data: datalist,
z: 100,
itemStyle: {
normal: {
color: function (params) {
// 柱状图每根柱子颜色
var colorList = ['#F75D5D', '#59ED4F', '#4C91E7'];
return colorList[params.dataIndex];
}
}
}
});
});
myChart.setOption(mapOption);
}
// 缩放和拖拽
function throttle(fn, delay) {
delay = delay || 0;
//定义变量
var currCall;
var lastCall = 0;
var lastExec = 0;
var timer = null;
var diff;
var scope;
var args;
function exec() {
lastExec = (new Date()).getTime();
timer = null;
fn.apply(scope, args || []);
}
var cb = function () {
currCall = (new Date()).getTime();
scope = this;
args = arguments;
diff = currCall - lastExec - delay;
clearTimeout(timer);
if (diff >= 0) {
exec();
} else {
timer = setTimeout(exec, -diff);
}
lastCall = currCall;
};
return cb;
}
// 获取横纵坐标
function getMousePos(e) {
var e = event || window.event;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var x = e.pageX || e.clientX + scrollX;
var y = e.pageY || e.clientY + scrollY;
return {
'x': x,
'y': y
};
}
var myChart = echarts.init(document.getElementById('map'));
myChart.showLoading();
$.get('../static/json/ChangSha.json', function (csJson) {
myChart.hideLoading();
echarts.registerMap('ChangSha', csJson);
//地图
var mapOption = {
// 时间轴
timeline: {
axisype: 'category',
autoPlay: true,
playInterval: 1500,
data: yearList,
label: {
fontSize: 10
}
},
animation: false,
title: {
show: false
},
tooltip: {
trigger: 'item'
},
backgroundColor: new echarts.graphic.RadialGradient(0.5, 0.5, 0.4, [{
offset: 0,
color: '#4b5769'
}, {
offset: 1,
color: '#404a59'
}]),
geo: {
map: 'ChangSha',
roam: true,
zoom: 4, // 地图初始大小
label: {
normal: {
show: true,
areaColor: '#eee'
}
},
// 地区块儿颜色
itemStyle: {
normal: {
areaColor: '#55C3FC',
borderColor: '#fff'
},
emphasis: {
areaColor: '#21AEF8'
}
}
},
series: []
};
//地图上显示饼图
setTimeout(renderEachCity, 0);
myChart.on('geoRoam', throttle(renderEachCity, 0));
myChart.setOption(mapOption);
// 点击显示饼图
myChart.on('click', function (e) {
if (e.componentSubType && e.componentSubType == "bar") {
// 先清除所有饼图
$('.pieTu').remove();
//获取数据
var datalist = [];
for (var i = 0; i < rawData.length; i++) {
if (i == e.seriesIndex) {
datalist.push({
name: 'PM25',
value: rawData[i].PM25
});
datalist.push({
name: 'PM10',
value: rawData[i].PM10
});
datalist.push({
name: 'O3',
value: rawData[i].O3
});
datalist.push({
name: 'NO2',
value: rawData[i].NO2
});
datalist.push({
name: 'SO2',
value: rawData[i].SO2
});
datalist.push({
name: 'CO',
value: rawData[i].CO
});
break;
}
}
// 创建遮挡层
var masker = document.createElement('div');
$(masker).addClass('masker').css({
width: '100%',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
zIndex: 8,
backgroundColor: 'rgba(0, 0, 0, 0)'
}).appendTo('#map');
// 创建饼图容器
var divX = getMousePos()['x'];
var divY = getMousePos()['y'];
var divObj = document.createElement('div');
$(divObj).attr('id', 'pie-echarts');
$(divObj).addClass('pieTu').css({
width: '250px',
height: '200px',
border: '1px solid #666',
position: 'absolute',
top: divY - 100 + 'px',
left: divX + 'px',
zIndex: 9,
}).appendTo('body');
// 创建饼图
var pieChart = echarts.init(document.getElementById('pie-echarts'));
var option = {
backgroundColor: 'rgba(0, 0, 0, 0.4)',
tooltip: {
trigger: 'item'
},
legend: {
show: false
},
series: [{
type: 'pie',
radius: ['0', '90%'],
center: ['50%', '50%'],
itemStyle: {
normal: {
label: {
color: '#fff',
position: 'inside'
},
borderColor: '#acefff',
// color: function(params) {
// var colorList = ['#F75D5D', '#59ED4F', '#4C91E7'];
// return colorList[params.dataIndex];
// }
},
emphasis: {
borderColor: '#ff0000',
borderWidth: 3
}
},
data: datalist
}]
};
pieChart.setOption(option);
// 点击遮挡层消失
$('.masker').click(function (e) {
this.remove();
$('.pieTu').remove();
return false;
});
}
return;
});
myChart.on('timelinechanged', function (timeLineIndex) {
let year = timeLineIndex.currentIndex + 2014
rawData = rawDatas[year]
setTimeout(renderEachCity, 0);
});
});
关于地图geojson数据可以前往这个网站查询,可自动生成相关文件。
有什么疑问和意见欢迎评论区留言,感谢各位的支持。