数据可视化:基于 Echarts + Python 实现的动态实时大屏范例一

近年来,数据可视化大屏的出现,掀起一番又一番的浪潮,众多企业主纷纷想要打造属于自己的 “酷炫吊炸天” 的霸道总裁大屏驾驶舱。今天为大家分享的是 【互联网企业数据分析】。

话不多说,开始分享干货,欢迎讨论!QQ和微信号相同 6550523

首先看动态效果图 :

再看实时分片数据图:

数据可视化:基于 Echarts + Python 实现的动态实时大屏范例一_第1张图片

一、 确定需求方案

1、确定产品上线部署的屏幕LED分辨率

1920px*1080px,F11全屏后占满整屏且无滚动条。其它分辨率也可自适应。

2、功能模块

  • 用户访问来源分析(饼图):  包括搜索引擎,联盟广告,直接访问
  • 访问地区分布(柱状图 + 地图 + 热力图):浙江、上海、广东、北京
  • 年龄分布(饼图):0岁以上、20-29岁、30-39岁、40-49岁、50岁以上
  • 职业分布(饼图):电子商务、教育、IT/互联网、金融、学生、其他
  • 兴趣分布(饼图):汽车、旅游、财经、教育、软件、其他
  • 终端设备分布(线图):Android + iOS移动端设备使用量
  • 频道访问量Top5(柱状图):实时显示最新Top5频道
  • 点赞量Top5(饼图): 实时显示最新Top5地区

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. 数据更新方式:摒弃了前端页面定时拉取的方式(这种方式带来严重的资源浪费),采用后端数据实时更新,实时推送到前端展示;

三、编码实现 (基于篇幅及可读性考虑,此处展示部分关键代码)

  • 前端html代码:




    
    
    index
    
    





页面加载中...

大数据可视化展板 —— 互联网企业数据分析

  • 用户访问来源
    访问地区分布
    • 12581189
    • 3912410
    • 总阅读量(pv)
    • 总收益
  • 终端设备分布
    频道访问量Top5
    点赞量Top5
  • 前端js代码:

var echarts_series_data = [
    {value: 335, name: '直接访问'},
    {value: 310, name: '邮件营销'},
    {value: 234, name: '联盟广告'},

];
$(function() {

    echarts_1();
    echarts_2();
    echarts_4();
    echarts_31();
    echarts_32();
    echarts_33();
    echarts_5();
    echarts_6();

    function echarts_1() {
        var myChart = echarts.init(document.getElementById('echart1'));

        option = {
            title: {
                // text: '某站点用户访问来源',
                // subtext: '纯属虚构',
                left: 'center'
            },
            tooltip: {
                trigger: 'item',
                formatter: '{a} 
{b} : {c} ({d}%)' }, legend: { // orient: 'vertical', left: 'left', // data: echarts_data }, series: [ { name: '访问来源', type: 'pie', radius: '55%', center: ['50%', '60%'], data: echarts_series_data, emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } function echarts_2() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('echart2')); var echarts_data = ['浙江', '上海', '江苏', '广东', '北京', '深圳', '安徽']; var echarts_series_data = [1500, 1200, 600, 200, 300, 300, 900]; option = { // backgroundColor: '#00265f', tooltip: { trigger: 'axis', axisPointer: { type: 'shadow'} }, grid: { left: '0%', top:'10px', right: '0%', bottom: '4%', containLabel: true }, xAxis: [{ type: 'category', data: echarts_data, axisLine: { show: true, lineStyle: { color: "rgba(255,255,255,.1)", width: 1, type: "solid" }, }, axisTick: { show: false, }, axisLabel: { interval: 0, // rotate:50, show: true, splitNumber: 15, textStyle: { color: "rgba(255,255,255,.6)", fontSize: '12', }, }, }], yAxis: [{ type: 'value', axisLabel: { //formatter: '{value} %' show:true, textStyle: { color: "rgba(255,255,255,.6)", fontSize: '12', }, }, axisTick: { show: false, }, axisLine: { show: true, lineStyle: { color: "rgba(255,255,255,.1 )", width: 1, type: "solid" }, }, splitLine: { lineStyle: { color: "rgba(255,255,255,.1)", } } }], series: [ { type: 'bar', data: echarts_series_data, barWidth:'35%', //柱子宽度 // barGap: 1, //柱子之间间距 itemStyle: { normal: { color:'#27d08a', opacity: 1, barBorderRadius: 5, } } } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } function echarts_5() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('echart5')); option = { dataset: { source: [ ['数量', '项目'], [ 28, 'C\C++'], [ 48, 'Java'], [ 61, 'Php'], [ 92, 'Python'], [ 101, 'Go'] ] }, // grid: {containLabel: true}, grid: { left: '0%', top:'10px', right: '0%', bottom: '4%', containLabel: true }, xAxis: [{ type: 'value', // type: 'category', // data: echarts_data, axisLine: { show: true, lineStyle: { color: "rgba(255,255,255,.1)", width: 1, type: "solid" }, }, axisTick: { show: false, }, axisLabel: { interval: 0, // rotate:50, show: true, splitNumber: 15, textStyle: { color: "rgba(255,255,255,.6)", fontSize: '12', }, }, }], yAxis: [{ type: 'category', // type: 'value', axisLabel: { //formatter: '{value} %' show: true, textStyle: { color: "rgba(255,255,255,.6)", fontSize: '12', }, }, axisTick: { show: false, }, axisLine: { show: true, lineStyle: { color: "rgba(255,255,255,.1 )", width: 1, type: "solid" }, }, splitLine: { lineStyle: { color: "rgba(255,255,255,.1)", } } }], series: [ { type: 'bar', encode: { // Map the "amount" column to X axis. x: '数量', // Map the "product" column to Y axis y: '产品' } } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } function echarts_4() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('echart4')); option = { tooltip: { trigger: 'axis', axisPointer: { lineStyle: { color: '#dddc6b' } } }, legend: { top:'0%', data:['安卓','IOS'], textStyle: { color: 'rgba(255,255,255,.5)', fontSize: '12', } }, grid: { left: '10', top: '30', right: '10', bottom: '10', containLabel: true }, xAxis: [{ type: 'category', boundaryGap: false, axisLabel: { textStyle: { color: "rgba(255,255,255,.6)", fontSize: 12, }, }, axisLine: { lineStyle: { color: 'rgba(255,255,255,.2)' } }, data: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24'] }, { axisPointer: {show: false}, axisLine: {show: false}, position: 'bottom', offset: 20, }], yAxis: [{ type: 'value', axisTick: {show: false}, axisLine: { lineStyle: { color: 'rgba(255,255,255,.1)' } }, axisLabel: { textStyle: { color: "rgba(255,255,255,.6)", fontSize: 12, }, }, splitLine: { lineStyle: { color: 'rgba(255,255,255,.1)' } } }], series: [ { name: '安卓', type: 'line', smooth: true, symbol: 'circle', symbolSize: 5, showSymbol: false, lineStyle: { normal: { color: '#0184d5', width: 2 } }, areaStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(1, 132, 213, 0.4)' }, { offset: 0.8, color: 'rgba(1, 132, 213, 0.1)' }], false), shadowColor: 'rgba(0, 0, 0, 0.1)', } }, itemStyle: { normal: { color: '#0184d5', borderColor: 'rgba(221, 220, 107, .1)', borderWidth: 12 } }, data: [3, 4, 3, 4, 3, 4, 3, 6, 2, 4, 2, 4,3, 4, 3, 4, 3, 4, 3, 6, 2, 4, 2, 4] }, { name: 'IOS', type: 'line', smooth: true, symbol: 'circle', symbolSize: 5, showSymbol: false, lineStyle: { normal: { color: '#00d887', width: 2 } }, areaStyle: { normal: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(0, 216, 135, 0.4)' }, { offset: 0.8, color: 'rgba(0, 216, 135, 0.1)' }], false), shadowColor: 'rgba(0, 0, 0, 0.1)', } }, itemStyle: { normal: { color: '#00d887', borderColor: 'rgba(221, 220, 107, .1)', borderWidth: 12 } }, data: [5, 3, 5, 6, 1, 5, 3, 5, 6, 4, 6, 4, 8, 3, 5, 6, 1, 5, 3, 7, 2, 5, 1, 4] }, ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } function echarts_6() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('echart6')); var dataStyle = { normal: { label: { show: false }, labelLine: { show: false }, //shadowBlur: 40, //shadowColor: 'rgba(40, 40, 40, 1)', } }; var placeHolderStyle = { normal: { color: 'rgba(255,255,255,.05)', label: {show: false,}, labelLine: {show: false} }, emphasis: { color: 'rgba(0,0,0,0)' } }; option = { color: ['#0f63d6', '#0f78d6', '#0f8cd6', '#0fa0d6', '#0fb4d6'], tooltip: { show: true, formatter: "{a} : {c} " }, legend: { itemWidth: 10, itemHeight: 10, itemGap: 12, bottom: '3%', data: ['浙江', '上海', '广东', '北京', '深圳'], textStyle: { color: 'rgba(255,255,255,.6)', } }, series: [ { name: '浙江', type: 'pie', clockWise: false, center: ['50%', '42%'], radius: ['59%', '70%'], itemStyle: dataStyle, hoverAnimation: false, data: [{ value: 80, name: '01' }, { value: 20, name: 'invisible', tooltip: {show: false}, itemStyle: placeHolderStyle }] }, { name: '上海', type: 'pie', clockWise: false, center: ['50%', '42%'], radius: ['49%', '60%'], itemStyle: dataStyle, hoverAnimation: false, data: [{ value: 70, name: '02' }, { value: 30, name: 'invisible', tooltip: {show: false}, itemStyle: placeHolderStyle }] }, { name: '广东', type: 'pie', clockWise: false, hoverAnimation: false, center: ['50%', '42%'], radius: ['39%', '50%'], itemStyle: dataStyle, data: [{ value: 65, //name: '03' }, { value: 35, //name: 'invisible', //tooltip: {show: false}, itemStyle: placeHolderStyle }] } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } function echarts_31() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('fb1')); option = { title: [{ text: '年龄分布', left: 'center', textStyle: { color: '#fff', fontSize:'16' } }], tooltip: { trigger: 'item', formatter: "{a}
{b}: {c} ({d}%)", position:function(p){ //其中p为当前鼠标的位置 return [p[0] + 10, p[1] - 10]; } }, legend: { top:'70%', itemWidth: 10, itemHeight: 10, data:['0岁以下','20-29岁','30-39岁','40-49岁','50岁以上'], textStyle: { color: 'rgba(255,255,255,.5)', fontSize:'12', } }, series: [ { name:'年龄分布', type:'pie', center: ['50%', '42%'], radius: ['40%', '60%'], color: ['#065aab', '#066eab', '#0682ab', '#0696ab', '#06a0ab','#06b4ab','#06c8ab','#06dcab','#06f0ab'], label: {show:false}, labelLine: {show:false}, data:[ {value:1, name:'0岁以下'}, {value:4, name:'20-29岁'}, {value:2, name:'30-39岁'}, {value:2, name:'40-49岁'}, {value:1, name:'50岁以上'}, ] } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } function echarts_32() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('fb2')); option = { title: [{ text: '职业分布', left: 'center', textStyle: { color: '#fff', fontSize: '16' } }], tooltip: { trigger: 'item', formatter: "{a}
{b}: {c} ({d}%)", position:function(p){ //其中p为当前鼠标的位置 return [p[0] + 10, p[1] - 10]; } }, legend: { top:'70%', itemWidth: 10, itemHeight: 10, data:['电子商务','教育','IT/互联网','金融','学生','其他'], textStyle: { color: 'rgba(255,255,255,.5)', fontSize:'12', } }, series: [ { name:'职业分布', type:'pie', center: ['50%', '42%'], radius: ['40%', '60%'], color: ['#065aab', '#066eab', '#0682ab', '#0696ab', '#06a0ab','#06b4ab','#06c8ab','#06dcab','#06f0ab'], label: {show:false}, labelLine: {show:false}, data:[ {value:5, name:'电子商务'}, {value:1, name:'教育'}, {value:6, name:'IT/互联网'}, {value:2, name:'金融'}, {value:1, name:'学生'}, {value:1, name:'其他'}, ] } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } function echarts_33() { // 基于准备好的dom,初始化echarts实例 var myChart = echarts.init(document.getElementById('fb3')); option = { title: [{ text: '兴趣分布', left: 'center', textStyle: { color: '#fff', fontSize: '16' } }], tooltip: { trigger: 'item', formatter: "{a}
{b}: {c} ({d}%)", position:function(p){ //其中p为当前鼠标的位置 return [p[0] + 10, p[1] - 10]; } }, legend: { top:'70%', itemWidth: 10, itemHeight: 10, data:['汽车','旅游','财经','教育','软件','其他'], textStyle: { color: 'rgba(255,255,255,.5)', fontSize:'12', } }, series: [ { name:'兴趣分布', type:'pie', center: ['50%', '42%'], radius: ['40%', '60%'], color: ['#065aab', '#066eab', '#0682ab', '#0696ab', '#06a0ab','#06b4ab','#06c8ab','#06dcab','#06f0ab'], label: {show:false}, labelLine: {show:false}, data:[ {value:2, name:'汽车'}, {value:3, name:'旅游'}, {value:1, name:'财经'}, {value:4, name:'教育'}, {value:8, name:'软件'}, {value:1, name:'其他'}, ] } ] }; // 使用刚指定的配置项和数据显示图表。 myChart.setOption(option); window.addEventListener("resize", function () { myChart.resize(); }); } }) //async_data(); function async_data() { // 异步加载数据 $.getJSON('json/echart1.json').done(function (data) { var myChart = echarts.init(document.getElementById('echart1')); myChart.setOption({ series: [{ data: data }] }); });//end $.getJSON $.getJSON('json/echart2.json').done(function (data) { var myChart = echarts.init(document.getElementById('echart2')); myChart.setOption({ xAxis: data["xAxis"], series:data["series"] }); }); //end $.getJSON $.getJSON('json/echart4.json').done(function (data) { var myChart = echarts.init(document.getElementById('echart4')); myChart.setOption({ legend: data["legend"], xAxis: data["xAxis"], series: data["series"] }); });//end $.getJSON $.getJSON('json/echart5.json').done(function (data) { var myChart = echarts.init(document.getElementById('echart5')); myChart.setOption({ dataset: data["dataset"] }); });//end $.getJSON $.getJSON('json/echart6.json').done(function (data) { var myChart = echarts.init(document.getElementById('echart6')); myChart.setOption({ legend: data["legend"], series: data["series"] }); });//end $.getJSON $.getJSON('json/echart31.json').done(function (data) { var myChart = echarts.init(document.getElementById('fb1')); // console.log(data["legend"]) myChart.setOption({ title: data["title"], legend: data["legend"], series: data["series"] }); });//end $.getJSON $.getJSON('json/echart32.json').done(function (data) { var myChart = echarts.init(document.getElementById('fb2')); // console.log(data["legend"]) myChart.setOption({ title: data["title"], legend: data["legend"], series: data["series"] }); });//end $.getJSON $.getJSON('json/echart33.json').done(function (data) { var myChart = echarts.init(document.getElementById('fb3')); // console.log(data["legend"]) myChart.setOption({ title: data["title"], legend: data["legend"], series: data["series"] }); });//end $.getJSON $.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 }
  • 后端python代码
#author QQ "6550523" or weixin "6550523"
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("file:///index.html"))
    self.webview.load(QUrl("http://localhost:8888/index.html"))
    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


  #按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()
    return new_webview


if __name__ == "__main__":
  app = QApplication(sys.argv)
  w = MainWindow()
  w.show()
  sys.exit(app.exec_())

四、上线运行

本次分享结束,欢迎讨论!QQ和微信号相同 6550523

引用:基于互联网大牛的前端改进一下,做了个可执行程序,获取数据后更新到页面上。

另外,这里有Golang实现的版本:https://blog.csdn.net/QQ6550523/article/details/106930211

你可能感兴趣的:(数据可视化案例,-,大屏电子看板,python,echarts教程)