近年来,数据可视化大屏的出现,掀起一番又一番的浪潮,众多企业主纷纷想要打造属于自己的“酷炫吊炸天”的霸道总裁大屏驾驶舱。今天为大家来分享的是 物流大数据服务平台。
话不多说,开始分享干货,欢迎讨论!
首先看动态效果图 :
一、 确定需求方案
最终样式图
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_())
四、上线运行
本次分享结束,欢迎讨论!
引用:基于互联网大牛的前端改进一下,做了个可执行程序,获取数据后更新到页面上