近年来,数据可视化大屏的出现,掀起一番又一番的浪潮,众多企业主纷纷想要打造属于自己的“酷炫吊炸天”的霸道总裁大屏驾驶舱。今天为大家来分享的是 物流大数据服务平台。
话不多说,开始分享干货,欢迎讨论!QQ微信同号: 6550523
首先看动态效果图 :
一、 确定需求方案
最终样式图
1、确定产品上线部署的屏幕LED分辨率
1920px*1080px,F11全屏后占满整屏且无滚动条。其它分辨率也可自适应。
2、功能模块
湖南货物收入
湖南省地图
全国地图
货物周转量
湖南高速公路
湖南省飞机场
湖南省业务量
货物周转量
3、部署方式
基于免安装可执行程序:支持Windows、Linux、Mac等各种操作系统;将程序复制到服务器上即可,无需其它环境依赖;
观看方式:既可在服务器上直接观看程序界面,也可在远程用浏览器打开播放,例如Chrome浏览器、360浏览器等。
二、整体架构设计
1、前端基于Echarts开源库设计,使用WebStorm编辑器;
2、后端基于Python Web实现,使用Pycharm编辑器;
3、数据传输格式:JSON;
4、数据源类型:目前已支持PostgreSQL、MySQL、Oracle、Microsoft SQL Server、SQLite、Excel表格等,还可以定制HTTP API接口方式或其它类型数据库。
5、数据更新方式:摒弃了前端页面定时拉取的方式(这种方式带来严重的资源浪费),采用后端数据实时更新,实时推送到前端展示;
三、编码实现 (基于篇幅及可读性考虑,此处展示部分关键代码)
1、前端html代码:
index
页面加载中...
湖南货物收入
湖南省地图
湖南省交通
运营数(辆)
线路总长度(公里)
客运总量(万人次)
日期
21059
26497
184448
2018年
18777
21140
188808
2017年
15757
20225
201143
2016年
17458
19567
202446
2015年
11323
14562
279854
2014年
全国地图
湖南省业务量
运营数(辆)
线路总长度(公里)
客运总量(万人次)
日期
21059
26497
184448
2018年
18777
21140
188808
2017年
15757
20225
201143
2016年
17458
19567
202446
2015年
11323
14562
279854
2014年
货物周转量
湖南高速公路
湖南省飞机场
2.前端JS代码
$(function () {
echart_1();
echart_2();
echart_3();
echart_4();
echart_map();
echart_5();
//echart_1湖南货物收入
function echart_1() {
chart_1_data = [{
value: 900.58,
name: '张家口',
itemStyle: {
normal: {
color: '#f845f1'
}
}
},
{
value: 1100.58,
name: '承德',
itemStyle: {
normal: {
color: '#ad46f3'
}
}
},
{
value: 1200.58,
name: '衡水',
itemStyle: {
normal: {
color: '#5045f6'
}
}
},
{
value: 1300.58,
name: '邢台',
itemStyle: {
normal: {
color: '#4777f5'
}
}
},
{
value: 1400.58,
name: '邯郸',
itemStyle: {
normal: {
color: '#44aff0'
}
}
},
{
value: 1500.58,
name: '保定',
itemStyle: {
normal: {
color: '#45dbf7'
}
}
},
{
value: 1500.58,
name: '秦皇岛',
itemStyle: {
normal: {
color: '#f6d54a'
}
}
},
{
value: 1600.58,
name: '石家庄',
itemStyle: {
normal: {
color: '#f69846'
}
}
},
{
value: 1800,
name: '唐山',
itemStyle: {
normal: {
color: '#ff4343'
}
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
},
{
value: 0,
name: "",
itemStyle: {
normal: {
color: 'transparent'
}
},
label: {
show: false
},
labelLine: {
show: false
}
}
]
// console.log(JSON.stringify( chart_1_data ));
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echart_1'));
option = {
//鼠标缩放和平移
roam: true,
tooltip: {
trigger: 'item',
formatter: "{a} {b} : {c}万元"
},
legend: {
x: 'center',
y: '15%',
data: ['张家口', '承德', '衡水', '邢台', '邯郸', '保定', '秦皇岛', '石家庄', '唐山'],
icon: 'circle',
textStyle: {
color: '#fff',
}
},
calculable: true,
series: [{
name: '',
type: 'pie',
//起始角度,支持范围[0, 360]
startAngle: 0,
//饼图的半径,数组的第一项是内半径,第二项是外半径
radius: [41, 100.75],
//支持设置成百分比,设置成百分比时第一项是相对于容器宽度,第二项是相对于容器高度
center: ['50%', '40%'],
//是否展示成南丁格尔图,通过半径区分数据大小。可选择两种模式:
// 'radius' 面积展现数据的百分比,半径展现数据的大小。
// 'area' 所有扇区面积相同,仅通过半径展现数据大小
roseType: 'area',
//是否启用防止标签重叠策略,默认开启,圆环图这个例子中需要强制所有标签放在中心位置,可以将该值设为 false。
avoidLabelOverlap: false,
label: {
normal: {
show: true,
formatter: '{c}万元'
},
emphasis: {
show: true
}
},
labelLine: {
normal: {
show: true,
length2: 1,
},
emphasis: {
show: true
}
},
data: chart_1_data
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
//echart_2湖南省地图
function echart_2() {
series_data = [{
name: '长沙市',
value: 100
}, {
name: '株洲市',
value: 96
}, {
name: '湘潭市',
value: 98
}, {
name: '衡阳市',
value: 80
}, {
name: '邵阳市',
value: 88
}, {
name: '岳阳市',
value: 79
}, {
name: '常德市',
value: 77,
}, {
name: '张家界市',
value: 33
}, {
name: '益阳市',
value: 69,
}, {
name: '郴州市',
value: 66
}, {
name: '永州市',
value: 22
}, {
name: '娄底市',
value: 51
}, {
name: '湘西土家族苗族自治州',
value: 44
}, {
name: '怀化市',
value: 9
}];
// console.log(JSON.stringify(data));
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echart_2'));
myChart.setOption(option = {
//鼠标缩放和平移
roam: true,
// backgroundColor: '#ffffff',
tooltip: {
trigger: 'item',
formatter: '{b} {c} (p / km2)'
},
visualMap: {
show: true,
min: 0,
max: 100,
left: 'left',
top: 'bottom',
text: ['高', '低'], // 文本,默认为数值文本
// realtime: true,
calculable: true,
// text文字颜色
textStyle:{
color:'#ffffff',
},
inRange: {
color: ['lightskyblue', 'yellow', 'orangered']
}
},
series: [{
type: 'map',
mapType: 'hunan',
zlevel: 2,
label: {
show: true
},
data: series_data
}]
});
// 使用刚指定的配置项和数据显示图表。
window.addEventListener("resize", function () {
myChart.resize();
});
}
// echart_map中国地图
function echart_map() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echart_map'));
var mapName = 'china'
var data = []
var toolTipData = [];
/*获取地图数据*/
myChart.showLoading();
var mapFeatures = echarts.getMap(mapName).geoJson.features;
myChart.hideLoading();
var geoCoordMap = {
'福州': [119.4543, 25.9222],
'长春': [125.8154, 44.2584],
'重庆': [107.7539, 30.1904],
'西安': [109.1162, 34.2004],
'成都': [103.9526, 30.7617],
'常州': [119.4543, 31.5582],
'北京': [116.4551, 40.2539],
'北海': [109.314, 21.6211],
'海口': [110.3893, 19.8516],
'长沙': [113.019455, 28.200103],
'上海': [121.40, 31.73],
'内蒙古': [106.82, 39.67]
};
var GZData = [
[{
name: '长沙'
}, {
name: '福州',
value: 95
}],
[{
name: '长沙'
}, {
name: '长春',
value: 80
}],
[{
name: '长沙'
}, {
name: '重庆',
value: 70
}],
[{
name: '长沙'
}, {
name: '西安',
value: 60
}],
[{
name: '长沙'
}, {
name: '成都',
value: 50
}],
[{
name: '长沙'
}, {
name: '常州',
value: 40
}],
[{
name: '长沙'
}, {
name: '北京',
value: 30
}],
[{
name: '长沙'
}, {
name: '北海',
value: 20
}],
[{
name: '长沙'
}, {
name: '海口',
value: 10
}],
[{
name: '长沙'
}, {
name: '上海',
value: 80
}],
[{
name: '长沙'
}, {
name: '内蒙古',
value: 80
}]
];
var convertData = function (data) {
var res = [];
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
var fromCoord = geoCoordMap[dataItem[0].name];
var toCoord = geoCoordMap[dataItem[1].name];
if (fromCoord && toCoord) {
res.push({
fromName: dataItem[0].name,
toName: dataItem[1].name,
coords: [fromCoord, toCoord]
});
}
}
return res;
};
var color = ['#c5f80e'];
var series = [];
[
['石家庄', GZData]
].forEach(function (item, i) {
console.log(i, item, item[0], item[1])
series.push({
name: item[0],
type: 'lines',
zlevel: 2,
symbol: ['none', 'arrow'],
symbolSize: 10,
effect: {
show: true,
period: 6,
trailLength: 0,
symbol: 'arrow',
symbolSize: 5
},
lineStyle: {
normal: {
color: color[i],
width: 1,
opacity: 0.6,
curveness: 0.2
}
},
data: convertData(item[1])
}, {
name: item[0],
type: 'effectScatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
brushType: 'stroke'
},
label: {
normal: {
show: true,
position: 'right',
formatter: '{b}'
}
},
symbolSize: function (val) {
return val[2] / 8;
},
itemStyle: {
normal: {
color: color[i]
}
},
data: item[1].map(function (dataItem) {
v = {
name: dataItem[1].name,
value: geoCoordMap[dataItem[1].name].concat([dataItem[1].value])
};
return v
})
});
});
option = {
//鼠标缩放和平移
roam: true,
tooltip: {
trigger: 'item'
},
geo: {
map: 'china',
label: {
emphasis: {
show: false
}
},
roam: true,
itemStyle: {
normal: {
borderColor: 'rgba(147, 235, 248, 1)',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [{
offset: 0,
color: 'rgba(175,238,238, 0)' // 0% 处的颜色
}, {
offset: 1,
color: 'rgba(47,79,79, .1)' // 100% 处的颜色
}],
globalCoord: false // 缺省为 false
},
shadowColor: 'rgba(128, 217, 248, 1)',
// shadowColor: 'rgba(255, 255, 255, 1)',
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10
},
emphasis: {
areaColor: '#389BB7',
borderWidth: 0
}
}
},
series: series
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
//echart_3货物周转量
function echart_3() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echart_3'));
data = [
{
name:'铁路货物',
type:'line',
areaStyle: {},
data:[3961.88, 4233.63, 4183.14, 3633.01, 3704.47]
},
{
name:'国家铁路货物',
type:'line',
areaStyle: {},
data:[3374.76, 3364.76, 3274.76, 3371.82, 3259.87]
},
{
name:'地方铁路货物',
type:'line',
areaStyle: {},
data:[14.77, 15.17, 13.17, 14.56, 15.84]
},
{
name:'合资铁路货物',
type:'line',
areaStyle: {},
data:[686.17,847.26,895.22,865.28,886.72]
},
{
name:'公路货物',
type:'line',
areaStyle: {},
data:[6133.47, 6577.89, 7019.56,6821.48,7294.59]
},
{
name:'水运货物',
type:'line',
areaStyle: {},
data:[509.60, 862.54, 1481.77,1552.79,1333.62]
}
]
// console.log(JSON.stringify(data))
// myChart.clear();
option = {
//鼠标缩放和平移
roam: true,
title: {
text: ''
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['铁路货物', '国家铁路货物', '地方铁路货物', '合资铁路货物', '公路货物', '水运货物'],
textStyle: {
color: '#fff'
},
// top: '8%',
},
grid: {
top: '40%',
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
color: ['#FF4949', '#FFA74D', '#FFEA51', '#4BF0FF', '#44AFF0', '#4E82FF', '#584BFF', '#BE4DFF', '#F845F1'],
xAxis: {
type: 'category',
boundaryGap: false,
data: ['2012年', '2013年', '2014年', '2015年', '2016年'],
splitLine: {
show: false
},
axisLine: {
lineStyle: {
color: '#fff'
}
}
},
yAxis: {
name: '亿吨公里',
type: 'value',
splitLine: {
show: false
},
axisLine: {
lineStyle: {
color: '#fff'
}
}
},
series: data
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
//湖南高速公路
function echart_4() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echart_4'));
myChart.setOption({
tooltip : {
trigger: 'item'
},
series: [{
type: 'map',
mapType: 'hunan'
}]
});
var geoCoordMap = {
'怀化': [109.999867, 27.518949],
'吉首': [109.741528, 28.332629],
'张家界': [110.491722, 29.112001],
'常德': [111.701486, 29.076683],
'益阳': [112.348741, 28.544124],
'岳阳': [113.126486, 29.382401],
'长沙': [113.019455, 28.200103],
'株洲': [113.163141, 27.8418],
'湘潭': [112.91977, 27.882141],
'邵阳': [111.467859, 27.21915],
'娄底': [112.012438, 27.745506],
'衡阳': [112.63809, 26.895225],
'永州': [111.577632, 26.460144],
'郴州': [113.039396, 25.81497]
};
var goData = [
[{
name: '张家界'
}, {
id: 1,
name: '常德',
value: 86
}],
[{
name: '吉首'
}, {
id: 1,
name: '常德',
value: 86
}],
[{
name: '常德'
}, {
id: 1,
name: '益阳',
value: 70
}],
[{
name: '益阳'
}, {
id: 1,
name: '长沙',
value: 95
}],
[{
name: '长沙'
}, {
id: 1,
name: '岳阳',
value: 70
}],
[{
name: '长沙'
}, {
id: 1,
name: '湘潭',
value: 80
}],
[{
name: '长沙'
}, {
id: 1,
name: '株洲',
value: 80
}],
[{
name: '长沙'
}, {
id: 1,
name: '衡阳',
value: 80
}],
[{
name: '衡阳'
}, {
id: 1,
name: '郴州',
value: 70
}],
[{
name: '衡阳'
}, {
id: 1,
name: '永州',
value: 70
}],
[{
name: '湘潭'
}, {
id: 1,
name: '娄底',
value: 60
}],
[{
name: '娄底'
}, {
id: 1,
name: '邵阳',
value: 75
}],
[{
name: '邵阳'
}, {
id: 1,
name: '怀化',
value: 75
}],
];
//值控制圆点大小
var backData = [
[{
name: '常德'
}, {
id: 1,
name: '张家界',
value: 80
}],
[{
name: '常德'
}, {
id: 1,
name: '吉首',
value: 66
}],
[{
name: '益阳'
}, {
id: 1,
name: '常德',
value: 86
}],
[{
name: '长沙'
}, {
id: 1,
name: '益阳',
value: 70
}],
[{
name: '岳阳'
}, {
id: 1,
name: '长沙',
value: 95
}],
[{
name: '湘潭'
}, {
id: 1,
name: '长沙',
value: 95
}],
[{
name: '株洲'
}, {
id: 1,
name: '长沙',
value: 95
}],
[{
name: '衡阳'
}, {
id: 1,
name: '长沙',
value: 95
}],
[{
name: '郴州'
}, {
id: 1,
name: '衡阳',
value: 80
}],
[{
name: '永州'
}, {
id: 1,
name: '衡阳',
value: 80
}],
[{
name: '娄底'
}, {
id: 1,
name: '湘潭',
value: 80
}],
[{
name: '邵阳'
}, {
id: 1,
name: '娄底',
value: 60
}],
[{
name: '怀化'
}, {
id: 1,
name: '邵阳',
value: 75
}],
];
var planePath = 'path://M1705.06,1318.313v-89.254l-319.9-221.799l0.073-208.063c0.521-84.662-26.629-121.796-63.961-121.491c-37.332-0.305-64.482,36.829-63.961,121.491l0.073,208.063l-319.9,221.799v89.254l330.343-157.288l12.238,241.308l-134.449,92.931l0.531,42.034l175.125-42.917l175.125,42.917l0.531-42.034l-134.449-92.931l12.238-241.308L1705.06,1318.313z';
var arcAngle = function (data) {
var j, k;
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
if (dataItem[1].id == 1) {
j = 0.2;
return j;
} else if (dataItem[1].id == 2) {
k = -0.2;
return k;
}
}
}
var convertData = function (data) {
var res = [];
for (var i = 0; i < data.length; i++) {
var dataItem = data[i];
var fromCoord = geoCoordMap[dataItem[0].name];
var toCoord = geoCoordMap[dataItem[1].name];
if (dataItem[1].id == 1) {
if (fromCoord && toCoord) {
res.push([{
coord: fromCoord,
}, {
coord: toCoord,
value: dataItem[1].value //线条颜色
}]);
}
} else if (dataItem[1].id == 2) {
if (fromCoord && toCoord) {
res.push([{
coord: fromCoord,
}, {
coord: toCoord
}]);
}
}
}
return res;
};
var color = ['#fff', '#FF1493', '#0000FF'];
var series = [];
[
['1', goData],
['2', backData]
].forEach(function (item, i) {
series.push({
name: item[0],
type: 'lines',
zlevel: 2,
symbol: ['arrow', 'arrow'],
//线特效配置
effect: {
show: true,
period: 6,
trailLength: 0.1,
symbol: 'arrow', //标记类型
symbolSize: 5
},
lineStyle: {
normal: {
width: 1,
opacity: 0.4,
curveness: arcAngle(item[1]), //弧线角度
color: '#fff'
}
},
edgeLabel: {
normal: {
show: true,
textStyle: {
fontSize: 14
},
formatter: function (params) {
var txt = '';
if (params.data.speed !== undefined) {
txt = params.data.speed;
}
return txt;
},
}
},
data: convertData(item[1])
}, {
name: item[0],
type: 'effectScatter',
coordinateSystem: 'geo',
zlevel: 2,
//波纹效果
rippleEffect: {
period: 2,
brushType: 'stroke',
scale: 3
},
label: {
normal: {
show: true,
color: '#fff',
position: 'right',
formatter: '{b}'
}
},
//终点形象
symbol: 'circle',
//圆点大小
symbolSize: function (val) {
return val[2] / 8;
},
itemStyle: {
normal: {
show: true
}
},
data: item[1].map(function (dataItem) {
return {
name: dataItem[1].name,
value: geoCoordMap[dataItem[1].name].concat([dataItem[1].value])
};
})
});
});
option = {
title: {
text: '',
subtext: '',
left: 'center',
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'item',
formatter: '{b}'
},
//线颜色及飞行轨道颜色
visualMap: {
left: 'left',
top: 'bottom',
text: ['高', '低'], // 文本,默认为数值文本
textStyle:{
color:'#ffffff',
},
// realtime: true,
calculable: true,
color: ['green','red', 'blue']
},
//地图相关设置
geo: {
map: 'hunan',
//视角缩放比例
zoom: 1,
//显示文本样式
label: {
normal: {
show: false, //没有数据的地方不显示文本
textStyle: {
color: '#fff'
}
},
emphasis: {
textStyle: {
color: '#fff'
}
}
},
//鼠标缩放和平移
roam: true,
itemStyle: {
normal: {
// color: '#ddd',
borderColor: 'rgba(147, 235, 248, 1)',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [{
offset: 0,
color: 'rgba(175,238,238, 0)' // 0% 处的颜色
}, {
offset: 1,
color: 'rgba( 47,79,79, .2)' // 100% 处的颜色
}],
globalCoord: false // 缺省为 false
},
shadowColor: 'rgba(128, 217, 248, 1)',
// shadowColor: 'rgba(255, 255, 255, 1)',
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10
},
emphasis: {
areaColor: '#389BB7',
borderWidth: 0
}
}
},
series: series
//series: []
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
//湖南省飞机场
function echart_5() {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('echart_5'));
function showProvince() {
var geoCoordMap = {
'长沙黄花国际机场': [113.226512, 28.192929],
'张家界荷花机场': [110.454598, 29.107223],
'常德桃花源机场': [111.651508, 28.921516],
'永州零陵机场': [111.622869, 26.340994],
'怀化芷江机场': [109.714784, 27.44615],
};
var data = [{
name: '长沙黄花国际机场',
value: 100
},
{
name: '张家界荷花机场',
value: 100
},
{
name: '常德桃花源机场',
value: 100
},
{
name: '永州零陵机场',
value: 100
},
{
name: '怀化芷江机场',
value: 100
}
];
var max = 480,
min = 9; // todo
var maxSize4Pin = 100,
minSize4Pin = 20;
var convertData = function (data) {
var res = [];
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name];
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
});
}
}
return res;
};
console.log(JSON.stringify(convertData(data)))
myChart.setOption(option = {
title: {
top: 20,
text: '',
subtext: '',
x: 'center',
textStyle: {
color: '#ccc'
}
},
legend: {
orient: 'vertical',
y: 'bottom',
x: 'right',
data: ['pm2.5'],
textStyle: {
color: '#fff'
}
},
visualMap: {
show: false,
min: 0,
max: 500,
left: 'left',
top: 'bottom',
text: ['高', '低'], // 文本,默认为数值文本
calculable: true,
seriesIndex: [1],
inRange: {}
},
geo: {
show: true,
map: 'hunan',
mapType: 'hunan',
label: {
normal: {},
//鼠标移入后查看效果
emphasis: {
textStyle: {
color: '#fff'
}
}
},
//鼠标缩放和平移
roam: true,
itemStyle: {
normal: {
// color: '#ddd',
borderColor: 'rgba(147, 235, 248, 1)',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [{
offset: 0,
color: 'rgba(175,238,238, 0)' // 0% 处的颜色
}, {
offset: 1,
color: 'rgba( 47,79,79, .2)' // 100% 处的颜色
}],
globalCoord: false // 缺省为 false
},
shadowColor: 'rgba(128, 217, 248, 1)',
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10
},
emphasis: {
areaColor: '#389BB7',
borderWidth: 0
}
}
},
series: [{
name: 'light',
type: 'map',
coordinateSystem: 'geo',
data: convertData(data),
itemStyle: {
normal: {
color: '#F4E925'
}
}
},
{
name: '点',
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'pin',
symbolSize: function (val) {
var a = (maxSize4Pin - minSize4Pin) / (max - min);
var b = minSize4Pin - a * min;
b = maxSize4Pin - a * max;
return a * val[2] + b;
},
label: {
normal: {
// show: true,
// textStyle: {
// color: '#fff',
// fontSize: 9,
// }
}
},
itemStyle: {
normal: {
color: '#F62157', //标志颜色
}
},
zlevel: 6,
data: convertData(data),
},
{
name: 'light',
type: 'map',
mapType: 'hunan',
geoIndex: 0,
aspectScale: 0.75, //长宽比
showLegendSymbol: false, // 存在legend时显示
label: {
normal: {
show: false
},
emphasis: {
show: false,
textStyle: {
color: '#fff'
}
}
},
roam: true,
itemStyle: {
normal: {
areaColor: '#031525',
borderColor: '#FFFFFF',
},
emphasis: {
areaColor: '#2B91B7'
}
},
animation: false,
data: data
},
{
name: ' ',
type: 'effectScatter',
coordinateSystem: 'geo',
data: convertData(data.sort(function (a, b) {
return b.value - a.value;
}).slice(0, 5)),
symbolSize: function (val) {
return val[2] / 10;
},
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
hoverAnimation: true,
label: {
normal: {
formatter: '{b}',
position: 'right',
show: true
}
},
itemStyle: {
normal: {
color: '#05C3F9',
shadowBlur: 10,
shadowColor: '#05C3F9'
}
},
zlevel: 1
},
]
});
}
showProvince();
// 使用刚指定的配置项和数据显示图表。
// myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
}
//点击跳转
// $('#chart_map').click(function () {
// window.location.href = './page/index.html';
// });
// $('.t_btn2').click(function () {
// window.location.href = "./page/index.html?id=2";
// });
// $('.t_btn3').click(function () {
// window.location.href = "./page/index.html?id=3";
// });
// $('.t_btn4').click(function () {
// window.location.href = "./page/index.html?id=4";
// });
// $('.t_btn5').click(function () {
// window.location.href = "./page/index.html?id=5";
// });
// $('.t_btn6').click(function () {
// window.location.href = "./page/index.html?id=6";
// });
// $('.t_btn7').click(function () {
// window.location.href = "./page/index.html?id=7";
// });
// $('.t_btn8').click(function () {
// window.location.href = "./page/index.html?id=8";
// });
// $('.t_btn9').click(function () {
// window.location.href = "./page/index.html?id=9";
// });
});
function async_data_chart_1() {
// 异步加载数据
$.getJSON('json/chart_1.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart_1'));
ret = myChart.setOption({
series: [{
data: data
}]
});
});//end $.getJSON
}
function async_data_chart_2() {
// 异步加载数据
$.getJSON('json/chart_2.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart_2'));
ret = myChart.setOption({
series: [{
data: data
}]
});
});//end $.getJSON
}
function async_data_chart_map() {
// 异步加载数据
$.getJSON('json/chart_map_effectScatter.json').done(function (data_effectScatter) {
$.getJSON('json/chart_map_lines.json').done(function (data_lines) {
var myChart = echarts.init(document.getElementById('echart_map'));
ret = myChart.setOption({
series: [{
name: data_lines["name"],
data: data_lines["data"]
}, {
name: data_effectScatter["name"],
data: data_effectScatter["data"]
}]
});
});//end $.getJSON
});//end $.getJSON
}
function async_data_chart_3() {
// 异步加载数据
$.getJSON('json/chart_3.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart_3'));
myChart.setOption({
legend: data["legend"],
xAxis: data["xAxis"],
yAxis: data["yAxis"],
series: data["series"]
});
});//end $.getJSON
}
function async_data_chart_4() {
// 异步加载数据
$.getJSON('json/chart_4.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart_4'));
myChart.setOption({
series: data
});
});//end $.getJSON
}
function async_data_chart_5() {
// 异步加载数据
$.getJSON('json/chart_5.json').done(function (data) {
var myChart = echarts.init(document.getElementById('echart_5'));
myChart.setOption({
series: [{data: data},
{data: data},
{data: data},
{data: data}]
});
});//end $.getJSON
}
function genTr(tr_data) {
// tr_data = data["tr"]
var $theadHtml = $(" ");
var $trTmp = $(" ");
for( var i = 0; i < tr_data.length; i++ ) {
$trTmp.append("" + tr_data[i] + " ");
}
$trTmp.appendTo($theadHtml)
return $theadHtml
}
function genTd(td_data){
var $tbodyHtml = $(" ");
for( var i = 0; i < td_data.length; i++ ) {
//动态创建一个tr行标签,并且转换成jQuery对象
var $trTmp = $(" ");
var tdTmp = td_data[i]
//往行里面追加 td单元格
for( var k = 0; k < tdTmp.length; k++ ) {
$trTmp.append(""+ tdTmp[k] +" ");
}
// $tbodyHtml.append($trTmp)
$trTmp.appendTo($tbodyHtml)
console.log("td_data %d", i)
}
return $tbodyHtml
}
function async_data_table_1() {
// 异步加载数据
$.getJSON('json/table_1.json').done(function (data) {
$("#table_1").empty();
genTr(data["tr"]).appendTo("#table_1");
genTd(data["td"]).appendTo("#table_1");
});//end $.getJSON
}
function async_data_table_2() {
// 异步加载数据
$.getJSON('json/table_2.json').done(function (data) {
$("#table_2").empty();
genTr(data["tr"]).appendTo("#table_2");
genTd(data["td"]).appendTo("#table_2");
});//end $.getJSON
}
function async_data_table_3() {
// 异步加载数据
$.getJSON('json/table_3.json').done(function (data) {
$("#table_3").empty();
genTr(data["tr"]).appendTo("#table_3");
genTd(data["td"]).appendTo("#table_3");
});//end $.getJSON
}
function async_data() {
async_data_chart_1();
async_data_chart_2();
async_data_chart_map();
async_data_chart_3();
async_data_chart_4();
async_data_chart_5();
async_data_table_1();
async_data_table_2();
async_data_table_3();
}
// async_data();
3、后端python代码
import _thread
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
from pyecharts import Geo
from PyQt5.QtCore import QUrl
from win32api import GetSystemMetrics
from PyQt5 import QtGui
from httpserver import *
from asyncJson import *
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.loadfinished = False
self.setWindowTitle('大屏展示')
self.showMaximized()
#全屏显示
self.showFullScreen()
self.isFullScreen = True
self.webview = WebEngineView()
self.webview.load(QUrl(index_url))
self.setCentralWidget(self.webview)
QShortcut(QtGui.QKeySequence("Escape"), self, self.Esc)
self.webview.loadFinished.connect(self.SetLoadFinished)
_thread.start_new_thread(HttpServer, ())
_thread.start_new_thread(self.ChangeData, ())
def SetLoadFinished(self):
self.loadfinished = True
#模拟刷新数据
def ChangeData(self):
while 1:
#页面加载完毕再开始刷新数据
if self.loadfinished == False :
# print("self.loadfinished == False")
continue
# print("self.loadfinished == True")
# change_all_json()
change_chart_1()
self.webview.page().runJavaScript("async_data_chart_1()")
change_chart_2()
self.webview.page().runJavaScript("async_data_chart_2()")
change_chart_map()
self.webview.page().runJavaScript("async_data_chart_map()")
time.sleep(1)
change_chart_3()
self.webview.page().runJavaScript("async_data_chart_3()")
change_chart_4()
self.webview.page().runJavaScript("async_data_chart_4()")
time.sleep(1)
change_chart_5()
self.webview.page().runJavaScript("async_data_chart_5()")
change_table(table_1_FILENAME)
self.webview.page().runJavaScript("async_data_table_1()")
change_table(table_2_FILENAME)
self.webview.page().runJavaScript("async_data_table_2()")
change_table(table_3_FILENAME)
self.webview.page().runJavaScript("async_data_table_3()")
time.sleep(1)
#按ESC全屏或缩小
def Esc(self):
if self.isFullScreen == True :
self.isFullScreen = False
#不加这句的话,标题栏就看不到了
self.showNormal()
#设置固定宽高
self.setGeometry(GetSystemMetrics(0)/2, GetSystemMetrics(1)/2, 1280, 768)
#再移动到屏幕中央
screen = QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2)
else:
self.showFullScreen()
self.isFullScreen = True
class WebEngineView(QWebEngineView):
windowList = []
# 重写createwindow()
def createWindow(self, QWebEnginePage_WebWindowType):
new_webview = WebEngineView()
new_window = MainWindow()
new_window.setCentralWidget(new_webview)
#new_window.show()
self.windowList.append(new_window) #注:没有这句会崩溃!!!
return new_webview
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
四、上线运行
本次分享结束,欢迎讨论!QQ微信同号: 6550523
引用:基于互联网大牛的前端改进一下,做了个可执行程序,获取数据后更新到页面上。