近年來,數據可視化大屏的出現,掀起一番又一番的浪潮,衆多企業主紛紛想要打造屬於自己的 “酷炫吊炸天” 的霸道總裁大屏駕駛艙。今天爲大家分享的是 【互聯網熱點分析案例】。
話不多說,開始分享乾貨,歡迎討論!QQ微信同號: 6550523
首先看動態效果圖 :
再看實時分片數據圖:
一、 確定需求方案
1、確定產品上線部署的屏幕LED分辨率
1280px*768px,F11全屏後佔滿整屏且無滾動條;其它分辨率屏幕均可自適應顯示。
2、功能模塊
- 1 水球圖
- 2 煙花圖
- 3 關係圖
- 4 中國地圖,熱力圖,飛線圖
- 5 大數據詞雲圖
3、部署方式
- 基於免安裝可執行程序:支持Windows、Linux、Mac等各種主流操作系統;將可執行程序exe複製到服務器上即可,無需其它環境依賴;
- 觀看方式:既可在服務器上直接觀看程序界面,也可遠程使用瀏覽器打開播放,支持Chrome瀏覽器、360瀏覽器等主流瀏覽器。
二、整體架構設計
- 前端基於Echarts開源庫設計,使用WebStorm編輯器;
- 後端基於Python Web實現,使用Pycharm編輯器;
- 數據傳輸格式:JSON;
- 數據源類型:目前已支持PostgreSQL、MySQL、Oracle、Microsoft SQL Server、SQLite、Excel表格等,還可以定製HTTP API接口方式或其它類型數據庫。
- 數據更新方式:摒棄了前端頁面定時拉取的方式(這種方式帶來嚴重的資源浪費),採用後端數據實時更新,實時推送到前端展示;
三、編碼實現 (基於篇幅及可讀性考慮,此處展示部分關鍵代碼)
-
前端html代碼
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" /> <title>互聯網+熱點分析案例</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="css/app.css" /> </head> <body class="bg06"> <header class="header"> <h3>互聯網熱點分析案例</h3> </header> <div class="wrapper"> <div class="container-fluid"> <div class="row fill-h"> <div class="col-lg-3 fill-h"> <div class="xpanel-wrapper xpanel-wrapper-1-2"> <div class="xpanel"> <div class="fill-h" id="ballChart"></div> </div> </div> <div class="xpanel-wrapper xpanel-wrapper-1-2"> <div class="xpanel"> <div class="fill-h" id="wordChart"></div> </div> </div> </div> <div class="col-lg-6 fill-h"> <div class="xpanel-wrapper xpanel-wrapper-1-1"> <!-- float:left; 平鋪,太奇葩了--> <div style="width: 50%; float:left;"> <p style="color: #5dc2fe; text-align: center" >日成交額突破</p> <p id="total_pv" style="font-size:66px; color: gold; text-align: center" > 3912410</p></div> <div style="width: 50%; float:left;"> <p style="color: #5dc2fe; text-align: center" >總收益突破</p> <p id="total_income" style="font-size:66px; color: firebrick; text-align: center" >222224444</p> </div> </div> <div class="xpanel-wrapper xpanel-wrapper-1-8"> <div class="xpanel no-padding no-bg"> <div class="fill-h" id="fireworksChart"></div> </div> </div> </div> <div class="col-lg-3 fill-h"> <div class="xpanel-wrapper xpanel-wrapper-1-3"> <div class="xpanel"> <div class="fill-h" id="relationChart"></div> </div> </div> <div class="xpanel-wrapper xpanel-wrapper-2-3"> <div class="xpanel"> <div class="fill-h" id="mapChart"></div> </div> </div> </div> </div> </div> </div> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript" src="https://cdn.bootcss.com/echarts/3.8.5/echarts.min.js"></script> <script type="text/javascript" src="js/echarts-wordcloud.min.js"></script> <script type="text/javascript" src="js/echarts-liquidfill.min.js"></script> <script type="text/javascript" src="js/echarts-map-china.js"></script> <script type="text/javascript" src="js/index.js"></script> <script type="text/javascript"> $(function() { /*************** 中國地圖 **************/ //初始化echarts實例 $(function() { // 基於準備好的dom,初始化echarts實例 var myChart = echarts.init(document.getElementById('mapChart')); 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); }); /*************** 煙花秀 **************/ //初始化echarts實例 const fireworksChart = echarts.init(document.getElementById("fireworksChart")); (function() { let r = function(max) { let m = max || 10; return Math.floor(Math.random() * m); }; let moonAndStars = { type: 'graph', data: (function() { let moonPosition = { x: 190, y: 0.5 } let moon = [{ symbolSize: 70, x: moonPosition.x, y: moonPosition.y }, { symbolSize: 60, x: moonPosition.x - 1.5, y: moonPosition.y - 1.5, itemStyle: { normal: { color: 'rgb(51, 51, 51)' } } }, { symbolSize: 0, x: 0, y: 0 }, { symbolSize: 0, x: 200, y: 100 }]; let num = 100; let stars = []; for (let i = 0; i < num; i++) { stars.push({ symbolSize: r(3), x: r(200), y: r(50) }) } return moon.concat(stars); })(), itemStyle: { normal: { color: '#ccc' } }, silent: true, z: -1 }; let roofs = [ /*三角形*/ [1, 2, 3, 4, 5, 4, 3, 2, 1], /*凸*/ [2, 2, 2, 4, 4, 4, 2, 2, 2], [2, 2, 2, 4, 20, 4, 2, 2, 2], [10, 9, 8, 7, 6, 5, 4, 3, 2, 1], [6, 6, 6, 6, 6, 5, 4, 3, 2, 1], [0.3, 1, 1.6, 2.5, 3, 3.5, 3.6, 3.7, 3.7, 3.6, 3.5, 3, 2.5, 1.6, 1, 0.3], [6, 6, 6, 6, 6, 2, 2, 2], [6, 5.5, 5, 4.5, 4, 3.5, 3, 2.5, 2, 1.5], [1, 1, 1, 1, 1, 1.5, 2, 2.5, 3, 3.5, 4], [1, 1, 1, 1, 1, 1, 1], [4, 4, 4, 2, 2, 2, 4, 4, 4] ]; let build = function(height) { let arr = [100]; let l = 14; let h = height || 50; let addFloor = function(arr, l) { let a = []; for (let i = 0; i < arr.length; i++) { a.push(arr[i] + l); } return a; }; for (let i = 0; i < l; i++) { let newRoof = addFloor(roofs[r(11)], r(h)); if (Math.random() < .5) { newRoof.reverse() } arr = arr.concat(newRoof); if (Math.random() < .5) { arr.push(0) } } return arr; }; let building = build(); let building2 = (function() { let b = build(100); for(let i = 0; i < b.length; i++) { if(b[i] > building[i]) { b[i] = b[i] - building[i]; } } return b; })() option = { title: { text: '', top: 20, left: 'center', textStyle: { fontSize: 20, color: '#fff', fontWeight: 'bold' } }, stack: true, grid: { bottom: 0, top: 0, left: -10, right: -10 }, xAxis: { data: [], silent: true, splitLine: { show: false }, axisLine: { show: false } }, yAxis: { silent: true, splitLine: { show: false }, axisLine: { show: false }, axisTick: { show: false }, axisLabel: { show: false } }, series: [{ type: 'bar', data: building, itemStyle: { normal: { color: 'rgb(38, 41, 57)' } }, animationDelay: function(idx) { return idx * 10; } }, { type: 'bar', data: building2, itemStyle: { normal: { color: 'rgb(28, 31, 47)' } }, animationDelay: function(idx) { return idx * 10 + 300; } }, { coordinateSystem: 'cartesian2d', type: 'lines', zlevel: 2, symbolSize: 3, effect: { show: true, period: 1, trailLength: 0.01, symbolSize: 5, symbol: 'pin', loop: true }, lineStyle: { normal: { color: '#BF3EFF', opacity: 0.005, //curveness: -0.05, width: 0.01, //opacity: 0.6, curveness: 0.1 } }, data: [{ coords: [ // 豎直向上 [40, 166], [40, 210] ] }, { // 水平向右 coords: [ [41, 165], [65, 165] ] }, { // 水平向左 coords: [ [39, 165], [15, 165] ] }, { // 垂直向下 coords: [ [40, 164], [40, 115] ] }, { //第一象限 coords: [ [40, 164], [55, 192] ] }, { //第一象限 coords: [ [40, 164], [56, 175] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { //第一象限 coords: [ [40, 164], [46, 197] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { //第一象限 coords: [ [41, 190], [47, 215] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第一象限 coords: [ [48, 190], [57, 205] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第一象限 coords: [ [52, 180], [62, 185] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第一象限 coords: [ [55, 170], [68, 171] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第二象限 coords: [ [39, 166], [24, 190] ] }, { //第二象限 coords: [ [40, 164], [24, 175] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { //第二象限 coords: [ [40, 164], [31, 195] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { //第二象限 coords: [ [25, 168], [13, 176] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第二象限 coords: [ [29, 175], [18, 195] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第二象限 coords: [ [33, 179], [24, 210] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第二象限 coords: [ [36, 185], [35, 210] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第三象限 coords: [ [40, 164], [26, 137] ] }, { //第三象限 coords: [ [40, 164], [34, 135] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { //第三象限 coords: [ [40, 164], [25, 153] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { //第三象限 coords: [ [39, 144], [36, 120] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第三象限 coords: [ [34, 144], [22, 123] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第三象限 coords: [ [30, 151], [21, 143] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第三象限 coords: [ [30, 159], [18, 157] ], lineStyle: { normal: { color: '#00FF33' } } }, { // 第四象限 coords: [ [40, 164], [55, 135] ] }, { // 第四象限 coords: [ [40, 164], [55, 152] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { // 第四象限 coords: [ [40, 164], [46, 135] ], lineStyle: { normal: { color: '#FFFFFF' } } }, { //第四象限 coords: [ [52, 160], [65, 153] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第四象限 coords: [ [52, 150], [62, 133] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第四象限 coords: [ [47, 144], [53, 123] ], lineStyle: { normal: { color: '#00FF33' } } }, { //第四象限 coords: [ [43, 134], [45, 113] ], lineStyle: { normal: { color: '#00FF33' } } }, ], animationDelay: 1100 }, { coordinateSystem: 'cartesian2d', type: 'lines', zlevel: -2, effect: { show: true, period: 1, trailLength: 0.01, symbolSize: 12, symbol: 'circle', loop: true }, lineStyle: { normal: { color: '#ccc', opacity: 0, curveness: 0 } }, data: [{ coords: [ [40, 25], [40, 165] ] }], animationDelay: 1100 }, { coordinateSystem: 'cartesian2d', type: 'lines', zlevel: -2, effect: { show: true, period: 1, trailLength: 0.01, symbolSize: 12, symbol: 'circle', loop: true }, lineStyle: { normal: { color: '#ccc', opacity: 0, curveness: 0 } }, data: [{ coords: [ [110, 25], [110, 165] ] }], animationDelay: 1100 }, { coordinateSystem: 'cartesian2d', type: 'lines', zlevel: 2, symbolSize: 3, effect: { show: true, period: 1, trailLength: 0.01, symbolSize: 5, symbol: 'pin', loop: true }, lineStyle: { normal: { color: '#ccc', opacity: 0.02, //curveness: -0.05, width: 0.01, //opacity: 0.6, curveness: 0.1 } }, data: [{ coords: [ // 豎直向上 [110, 166], [110, 210] ] }, { // 水平向右 coords: [ [111, 165], [135, 165] ] }, { // 水平向左 coords: [ [109, 165], [85, 165] ] }, { // 垂直向下 coords: [ [110, 164], [110, 115] ] }, { //第一象限 coords: [ [110, 164], [125, 192] ] }, { //第一象限 coords: [ [110, 164], [126, 175] ], lineStyle: { normal: { color: '#DD2222' } } }, { //第一象限 coords: [ [110, 164], [116, 197] ], lineStyle: { normal: { color: '#DD2222' } } }, { //第一象限 coords: [ [111, 190], [117, 215] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第一象限 coords: [ [118, 190], [127, 205] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第一象限 coords: [ [122, 180], [132, 185] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第一象限 coords: [ [125, 170], [138, 171] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第二象限 coords: [ [109, 166], [94, 190] ] }, { //第二象限 coords: [ [110, 164], [94, 175] ], lineStyle: { normal: { color: '#DD2222' } } }, { //第二象限 coords: [ [110, 164], [101, 195] ], lineStyle: { normal: { color: '#DD2222' } } }, { //第二象限 coords: [ [95, 168], [83, 176] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第二象限 coords: [ [99, 175], [88, 195] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第二象限 coords: [ [103, 179], [94, 210] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第二象限 coords: [ [106, 185], [105, 210] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第三象限 coords: [ [110, 164], [96, 137] ] }, { //第三象限 coords: [ [110, 164], [104, 135] ], lineStyle: { normal: { color: '#DD2222' } } }, { //第三象限 coords: [ [110, 164], [95, 153] ], lineStyle: { normal: { color: '#DD2222' } } }, { //第三象限 coords: [ [109, 144], [106, 120] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第三象限 coords: [ [104, 144], [92, 123] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第三象限 coords: [ [100, 151], [91, 143] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第三象限 coords: [ [100, 159], [88, 157] ], lineStyle: { normal: { color: '#FFFF00' } } }, { // 第四象限 coords: [ [110, 164], [125, 135] ] }, { // 第四象限 coords: [ [110, 164], [125, 152] ], lineStyle: { normal: { color: '#DD2222' } } }, { // 第四象限 coords: [ [110, 164], // 紅色象限位置錯亂 由 [555, 164] 改爲[110, 164] [116, 135] ], lineStyle: { normal: { color: '#DD2222' } } }, { //第四象限 coords: [ [122, 160], [135, 153] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第四象限 coords: [ [122, 150], [132, 133] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第四象限 coords: [ [117, 144], [123, 123] ], lineStyle: { normal: { color: '#FFFF00' } } }, { //第四象限 coords: [ [113, 134], [115, 113] ], lineStyle: { normal: { color: '#FFFF00' } } }, ], animationDelay: 1100 }], animationEasing: 'elasticOut', animationDelayUpdate: function(idx) { return idx * 5; } }; fireworksChart.setOption(option); })(); /*************** 關係圖 **************/ //初始化echarts實例 const relationChart = echarts.init(document.getElementById("relationChart")); const relationOpt = { animationDurationUpdate: 500, animationEasingUpdate: 'quinticInOut', label: { normal: { show: true, textStyle: { fontSize: 14 } } }, series: [{ type: 'graph', symbolSize: 50, focusNodeAdjacency: true, roam: true, layout: 'force', force: { repulsion:320 //斥力因子,值越大,斥力越大 }, label: { normal: { show: true, textStyle: { fontSize: 14 }, } }, edgeSymbolSize: [4, 50], edgeLabel: { normal: { show: true, textStyle: { fontSize: 14 }, formatter: "{c}" } }, categories: [{ name: '全棧', itemStyle: { normal: { color: '#f2637b' } } }, { name: '前端', itemStyle: { normal: { color: "#eaa674", } } }, { name: '移動端', itemStyle: { normal: { color: "#3aa1ff", } } }, { name: '服務端', itemStyle: { normal: { color: "#4ecb73", } } }], data: [{ name: '全棧', category: 0, draggable: true }, { name: '前端', category: 1, draggable: true }, { name: '移動端', category: 2, draggable: true }, { name: '服務端', category: 3, draggable: true }, { name: 'HTML', category: 1, draggable: true, }, { name: 'CSS', category: 1, draggable: true, }, { name: 'JavaScript', category: 1, draggable: true, }, { name: 'TypeScript', category: 1, draggable: true, }, { name: 'Java', category: 3, draggable: true, }, { name: 'PHP', category: 3, draggable: true, }, { name: 'Python', category: 3, draggable: true, }, { name: 'Andriod', category: 2, draggable: true, }, { name: 'Object-C', category: 2, draggable: true, }, { name: 'Swift', category: 2, draggable: true, }], links: [{ source: 0, target: 1, value: '' }, { source: 0, target: 2, value: '' }, { source: 0, target: 3, value: '' }, { source: 1, target: 4, value: '' }, { source: 1, target: 5, value: '' }, { source: 1, target: 6, value: '' }, { source: 1, target: 7, value: '' }, { source: 6, target: 7, value: '超集' }, { source: 3, target: 8, value: '' }, { source: 3, target: 9, value: '' }, { source: 3, target: 10, value: '' }, { source: 9, target: 10, value: '腳本' }, { source: 2, target: 11, value: '' }, { source: 2, target: 12, value: '' }, { source: 2, target: 13, value: '' }, { source: 12, target: 13, value: 'iOS' }], lineStyle: { normal: { opacity: 0.9, width: 2, curveness: 0 } } }] }; relationChart.setOption(relationOpt); console.log(JSON.stringify(relationOpt.series[0].data)) console.log(JSON.stringify(relationOpt.series[0].categories)) console.log(JSON.stringify(relationOpt.series[0].links)) /*************** 水球 **************/ //https://github.com/ecomfe/echarts-liquidfill //初始化echarts實例 const ballChart= echarts.init(document.getElementById("ballChart")); const ballOpt = { series: [{ type: 'liquidFill', radius: '95%', // label: { // show: false // }, shape: 'path://M367.855,428.202c-3.674-1.385-7.452-1.966-11.146-1.794c0.659-2.922,0.844-5.85,0.58-8.719 c-0.937-10.407-7.663-19.864-18.063-23.834c-10.697-4.043-22.298-1.168-29.902,6.403c3.015,0.026,6.074,0.594,9.035,1.728 c13.626,5.151,20.465,20.379,15.32,34.004c-1.905,5.02-5.177,9.115-9.22,12.05c-6.951,4.992-16.19,6.536-24.777,3.271 c-13.625-5.137-20.471-20.371-15.32-34.004c0.673-1.768,1.523-3.423,2.526-4.992h-0.014c0,0,0,0,0,0.014 c4.386-6.853,8.145-14.279,11.146-22.187c23.294-61.505-7.689-130.278-69.215-153.579c-61.532-23.293-130.279,7.69-153.579,69.202 c-6.371,16.785-8.679,34.097-7.426,50.901c0.026,0.554,0.079,1.121,0.132,1.688c4.973,57.107,41.767,109.148,98.945,130.793 c58.162,22.008,121.303,6.529,162.839-34.465c7.103-6.893,17.826-9.444,27.679-5.719c11.858,4.491,18.565,16.6,16.719,28.643 c4.438-3.126,8.033-7.564,10.117-13.045C389.751,449.992,382.411,433.709,367.855,428.202z', outline: { show: false }, backgroundStyle: { borderColor: '#156ACF', borderWidth: 1, shadowColor: 'rgba(0, 0, 0, 0.4)', shadowBlur: 20 }, data: [0.6, 0.5, 0.4, 0.3] }] }; ballChart.setOption(ballOpt); /*************** 詞雲 **************/ //https://github.com/ecomfe/echarts-wordcloud //初始化echarts實例 const wordChart= echarts.init(document.getElementById("wordChart")); const wordOpt = { series: [{ type: 'wordCloud', shape: 'circle', //circle cardioid diamond triangle-forward triangle left: 0, right: 0, top: 0, right: 0, width: '100%', height: '100%', gridSize: 0, //值越大,word間的距離越大,單位像素 sizeRange: [10, 32], //word的字體大小區間,單位像素 rotationRange: [-90, 90], //word的可旋轉角度區間 textStyle: { normal: { color: function() { return 'rgb(' + [ Math.round(Math.random() * 160), Math.round(Math.random() * 160), Math.round(Math.random() * 160) ].join(',') + ')'; } }, emphasis: { shadowBlur: 2, shadowColor: '#000' } }, data: [{ name: '數據可視化', value: 3000, // textStyle: { // normal: {color: '#f52f55'}, // emphasis: {} // } }, { name: '大數據', value: 2181 }, { name: '雲計算', value: 1386 }, { name: '物聯網', value: 2055 }, { name: '移動互聯網', value: 2467 }, { name: '人工智能', value: 2244 }, { name: '深度學習', value: 1898 }, { name: '機器學習', value: 1484 }, { name: '區塊鏈', value: 3865 }, { name: '互聯網+', value: 2222 }, { name: '智能合約', value: 366 }, { name: '比特幣', value: 360 }, { name: '數據挖掘', value: 273 }] }], backgroundColor: 'rgba(100, 255, 255, 0.6)' }; wordChart.setOption(wordOpt); /********** 窗口大小改變時,重置報表大小 ********************/ window.onresize = function() { wordChart.resize(); ballChart.resize(); relationChart.resize(); fireworksChart.resize(); // mapChart.resize(); }; }); </script> </body> </html>
-
前端JS代碼
var jsonFileNameWordCloud = "/json/wordCloud.json" var idWordCloud = "wordChart" function async_chart_wordCloud() { // 異步加載數據 $.getJSON(jsonFileNameWordCloud).done(function (data) { var element = document.getElementById(idWordCloud); console.log("async_chart_wordCloud", element, jsonFileNameWordCloud) var myChart = echarts.init(element); console.log(data) myChart.setOption({ series: [{ data: data }] }); });//end $.getJSON } var relationChartjsonFileName = "/json/relationChart.json" var relationChartId = "relationChart" function async_chart_relationChart() { // 異步加載數據 $.getJSON(relationChartjsonFileName).done(function (data) { var element = document.getElementById(relationChartId); console.log("async_chart_wordCloud", element, relationChartjsonFileName) var myChart = echarts.init(element); console.log(data) myChart.setOption({ series: [{ categories: data["categories"], links: data["links"], data: data["data"] }] }); });//end $.getJSON } var mapChartjsonFileNameEffectScatter = "/json/chart_map_effectScatter.json" var mapChartjsonFileNameLines = "/json/chart_map_lines.json" var mapChartId = "mapChart" function async_data_chart_map() { // 異步加載數據 $.getJSON(mapChartjsonFileNameEffectScatter).done(function (data_effectScatter) { $.getJSON(mapChartjsonFileNameLines).done(function (data_lines) { var myChart = echarts.init(document.getElementById(mapChartId)); 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_common() { $.getJSON('json/common.json').done(function (data) { document.getElementById('total_pv').innerText = data["total_pv"] document.getElementById('total_income').innerText = data["total_income"] });//end $.getJSON } var liquidFillJsonFileName = "/json/liquidFill.json" var liquidFillId = "ballChart" function async_chart_liquidFill() { // 異步加載數據 $.getJSON(liquidFillJsonFileName).done(function (data) { var element = document.getElementById(liquidFillId); console.log(element, liquidFillJsonFileName) var myChart = echarts.init(element); console.log(data) myChart.setOption({ series: [{ data: data }] }); });//end $.getJSON } function async_data(){ async_chart_wordCloud(); async_chart_relationChart(); async_data_chart_map(); async_data_common(); async_chart_liquidFill(); } async_data();
-
後端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()
self.webview.page().runJavaScript("async_data()")
time.sleep(3)
#按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
感謝:本項目引用了互聯網大牛的前端代碼,然後定製開發實現了後端服務器,最終實現了可視化大屏的完整方案。