大屏展示页面制作全程

918 阅读2分钟

完成效果

访问地址:http://106.75.179.94/bigscreen/#/

源码虽然全是我写的,但是属于公司,所以不发出来

使用的是vue2,dataV,echart

大屏实践案例:

gitee.com/zhufei_yao/…

dataV组件库和文档:

gitee.com/jiasichen/d… datav.jiaminghi.com/guide/#%E7%… charts.jiaminghi.com/config/

echart案例库:

www.makeapie.com/explore.htm…

echart学习:

先看:www.runoob.com/echarts/ech…

再看:echarts.apache.org/zh/option.h…

最后看(完整大全)www.bbsmax.com/A/nAJvKq9G5…

案例里可取的点

项目部分模仿下面这个案例的: gitee.com/zhufei_yao/…

rem适配

    var width = docEl.getBoundingClientRect().width;
    var docEl = doc.documentElement;
    // 设置成24等份,设计稿时1920px的,这样1rem就是80px
    var rem = width / 24;
    docEl.style.fontSize = rem + "px";

grid布局

grid-template-columns: 2fr 3fr 5fr 3fr 2fr;

我因为不习惯换成flex 配合rem了

resize时也要更新chart

当窗口resize时,自动调用chart.resize

  created() {
    let timer = null;
    //可以加个防抖
    window.addEventListener(
      "resize",
      () => {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
            this.$echarts.init(document.getElementById("bodyChart")).resize();
          }
        }, 300);
      },
      false
    );
  },

或者学上面案例的,使用mixins混入,那么图表chart就要写在data里。

个人采取的自适应方案

先分成上下几块,用vh来限定高度 左右的用rem,就用案例那样的 resize的时候获取clientWidth,再/24,确保24rem等于宽度100% 我中间三块,可以用0.2rem的padding,5.8,12,5.8,0.2的padding

也可以用width:25%,50%,25% 也可以用flex 也可以用案例的grid

echart基本配置

var option = {
    		//标题
            title: {
                text: '第一个 ECharts 实例'
            },	
            tooltip: {},//提示框
            legend: {//图例图形
                data:['销量']
            },
            xAxis: {//配置要在 X 轴显示的项:
                data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
            },
            yAxis: {},//配置要在 Y 轴显示的项。
            series: [{
                name:'销量',// 系列名称
                type: 'bar',// 系列图表类型
				tooltip: {//是否显示提示框
              		show: false,
            	},
                data: [5, 20, 36, 10, 10, 20],//数据
            }]
        };
 bar: {
        barMinHeight: 0,          // 最小高度改为0
        // barWidth: null,        // 默认自适应
        barGap: '30%',            // 柱间距离,默认为柱形宽度的30%,可设固定值
        barCategoryGap : '20%',   // 类目间柱形距离,默认为类目间距的20%,可设固定值
        itemStyle: {
            normal: {
                // color: '各异',
                barBorderColor: '#fff',       // 柱条边线
                barBorderRadius: 0,           // 柱条边线圆角,单位px,默认为0
                barBorderWidth: 1,            // 柱条边线线宽,单位px,默认为1
                label: {
                    show: false
                    // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
                    //           'inside'|'left'|'right'|'top'|'bottom'
                    // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
                }
            },
            emphasis: {//高亮的样式
                // color: '各异',
                barBorderColor: 'rgba(0,0,0,0)',   // 柱条边线
                barBorderRadius: 0,                // 柱条边线圆角,单位px,默认为0
                barBorderWidth: 1,                 // 柱条边线线宽,单位px,默认为1
                label: {
                    show: false
                    // position: 默认自适应,水平布局为'top',垂直布局为'right',可选为
                    //           'inside'|'left'|'right'|'top'|'bottom'
                    // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
                }
            }
        }
    },

类目轴配置

也就是一般的柱形type: "category",

默认色板
    // 默认色板
    color: ['#ff7f50','#87cefa','#da70d6','#32cd32','#6495ed',
            '#ff69b4','#ba55d3','#cd5c5c','#ffa500','#40e0d0',
            '#1e90ff','#ff6347','#7b68ee','#00fa9a','#ffd700',
            '#6699FF','#ff6666','#3cb371','#b8860b','#30e0e0'],
#xAxis
type = 'category'	类目轴
目前我只看类目轴的属性		可通过 xAxis.data 设置类目数据
show = true 是否显示 x 轴。
position	'top''bottom' 坐标在下还是在上
offset	偏移坐标
name 坐标轴名字	目前不需要,相关的不看
inverse	反转
boundaryGap 两边留白 默认为 true
min	坐标轴刻度最小值。类目轴不用关心这个
max	坐标轴刻度最大值。
triggerEvent	坐标轴的标签是否响应和触发鼠标事件
axisLine	坐标轴轴线相关设置。
	show = true	是否显示坐标轴轴线
	lineStyle	坐标轴线
		xAxis.axisLine.lineStyle. color = '#333'	坐标轴线线的颜色。
	axisTick	坐标轴刻度
axisLabel	坐标轴刻度标签
	axisLabel. color	刻度标签文字的颜色;支持回调函数
	fontStyle 
	fontWeight 
	fontFamily 
	fontSize 
	align	文字水平对齐方式,默
	verticalAlign	文字垂直对齐方式,
	lineHeight	
	backgroundColor	文字块背景色。
	borderColor
	borderWidth
	borderRadius
	padding
	阴影
	文字块的宽度
	高度
	textBorderColor	文字本身的描边颜色
	rich	在 rich 里面,可以自定义富文本样式。利用富文本样式,可以在标签中做出非常丰富的效果。
splitLine 坐标轴在 grid 区域中的分隔线。
data 类目轴的数据,设置了就说明是类目轴;
data. textStyle有以下标签属性
{ color , fontStyle , fontWeight , fontFamily , fontSize , align , verticalAlign , lineHeight , backgroundColor , borderColor , borderWidth , borderRadius , padding , shadowColor , shadowBlur , shadowOffsetX , shadowOffsetY , width , height , textBorderColor , textBorderWidth , textShadowColor , textShadowBlur , textShadowOffsetX , textShadowOffsetY , rich }

横向类目轴

亮晶晶 前面一段代码是数据的,可以不用管,需要知道的是顺序,坐标是从下到上拿数据的,阴影的颜色应该和本来的颜色一致,这样才会亮晶晶,轴长由data转变成

{value:xx, itemStyle: {
          normal: {
            borderWidth: 1,
            shadowBlur: 20,
            borderColor: color[i],
            shadowColor: color[i],
          },
        },}

组成的数组。 具体为 标签:数组showName

0: "肾上腺"
1: "头颈"
2: "肾"
3: "眼睛"
4: "肝"
5: "肺"

轴:数组对象Array(6)

0:
itemStyle: Object
  normal: Object
    borderColor: "#00ffff"
    borderWidth: 1
    shadowBlur: 20
    shadowColor: "#00ffff"
value:1
1: {__ob__: Observer}
2: {__ob__: Observer}
3: {__ob__: Observer}
4: {__ob__: Observer}
5: {__ob__: Observer}
//颜色列表
    let colorList = [
      "#00ffff",
      "#006ced",
      "#00cfff",
      "#ffe000",
      "#ffa800",
      "#ff5b00",
    ];
    //取出病症的值,深拷贝 解除引用 以便排序
    let arr = JSON.parse(
      JSON.stringify(this.$store.state.res?.dataShareSiteList)
    );
    function arrayObjSortByKey(array, key) {
      return array.sort(function (a, b) {
        var x = a[key];
        var y = b[key];
        return x > y ? -1 : x < y ? 1 : 0;
      });
    }
    //数组对象,按照对象的属性进行排序
    arrayObjSortByKey(arr, "total");
    //只取前四个最大的来展示,如果第一大和其他差距超过8倍,就不要其他了
    for (let i = 0; i < 6; i++) {
      let color = [
        "#00ffff",
        "#006ced",
        "#00cfff",
        "#ffe000",
        "#ffa800",
        "#ff5b00",
      ].reverse();
      // if(arr[0]&&i!=0&&arr[0].total/arr[i].total>8){
      //   break;
      // }
      this.showName.push(arr[i].name);
      this.showValue.push({
        value: arr[i].total,
        //自定义标签样式,仅对该数据项有效
        //自定义特殊 itemStyle,仅对该数据项有效
        itemStyle: {
          normal: {
            borderWidth: 1,
            shadowBlur: 20,
            borderColor: color[i],
            shadowColor: color[i],
          },
        },
      });
    }
let chart2 = this.$echarts.init(
      document.getElementById("little-body-chart")
    );
    chart2.setOption({
      grid: [
        {
          x: "32%",
          y: "0%",
          width: "50%",
          height: "100%",
        },
      ],
      xAxis: [
        {
          gridIndex: 0,
          axisTick: {
            show: false,
          },
          axisLabel: {
            show: false,
          },
          splitLine: {
            show: false,
          },
          axisLine: {
            show: false,
          },
        },
      ],
      yAxis: [
        {
          data: this.showName.reverse(),
          axisTick: {
            show: false,
          },
          axisLabel: {
            show: true,
            color: "#fff",
            rich: {
              a: {
                color: "red",
                lineHeight: 10,
              },
            },
          },
          splitLine: {
            show: false,
          },
          axisLine: {
            show: false,
            lineStyle: {
              color: "#6173a3",
            },
          },
        },
      ],
      series: [
        {
          type: "bar",
          barWidth: "20%",
          itemStyle: {
            normal: {
              color: function (params) {
                return colorList[params.dataIndex];
              },
              // color: '#86c9f4'
            },
          },
          data: this.showValue.reverse(),
        },
      ],
    });

地图学习

地图: gitee.com/vijtor/vue-…

解说上面的案例:www.jb51.net/article/199… www.makeapie.com/explore.htm…

地图钻取:

w3c地图教程:www.w3cschool.cn/echarts_tut…

ECharts 地图绘制与钻取简易接口

www.cnblogs.com/weigaojie/p…

example.maxiaoqu.com/map-geoJson…

gitee.com/maxiaoqu/ec…

地图属性: www.cnblogs.com/zhangxiaoxi…

取图网站: datav.aliyun.com/tools/atlas…

取图和加载

我要实现的是广东+澳门和香港;下载全国json文件,可以看到每个地点是一个对象;拿下想要的地方的对象字段就可以随意组合了 于是我在全国里找到了澳门和香港的json相关字段。加到了广东json文件里。就可以了

地图加载也可以不用jq的xhr获取,改用 本地json获取,使用require语法,这里感谢小单的帮忙;我这被误导以为只能xhr获取或者js加载

#vue
<script>
let guangdongJson = require('./guangdong.json')
export default {
  data() {
    return {
      chart:null,
    };
  },
  mounted() {
    this.initMap();
  },
  methods: {
    initMap() {
        var echarts = this.$echarts
        this.chart = echarts.init(document.getElementById("bottomLeft"));
        this.chart.hideLoading();
        echarts.registerMap("广东", guangdongJson);

地图中鼠标移入移除事件

地图鼠标移入不变色: blog.csdn.net/qq_38402878…

常见actionAPI: www.cnblogs.com/sminocence/…

鼠标移入移除事件:

blog.csdn.net/qq_36895045… www.cnblogs.com/xtreme/p/13…

 this.chart.setOption(option);
     this.chart.on('mouseover',(params)=>{
          console.log(params,params.name)
          let xiao = document.getElementById('showTip')
          var evt = params.event;
          xiao.style.left = evt.offsetX-200+'px';
          xiao.style.top = evt.offsetY+'px';
          if(params.componentType=='geo'){
              xiao.innerHTML =   '<div style="background:#fff;border-radius:10px;padding-top:10px;box-shadow:0 0 10px #666">' +
                  '<div style="color:#fff;height:20px;border-radius:6px;font-size:12px;line-height:20px;background-color:#5861a2;text-align:center;margin:0 2px;">' +
                  params.name +
                  "</div>" +
                  '<div style="text-align:center;color:#494949;padding:8px 6px">' +
                  '<span style="font-size:18px;font-weight:bold;">' +
                  "节点:" +
                  params.name +
                  " " +
                  "</span>" +
                  "</div>" +
                  "</div>";
          }
        
        })
        this.chart.on('mouseout',function(p){
          let xiao = document.getElementById('showTip')
          xiao.innerHTML = ''
    });
  • 鼠标移入类目轴标签事件

参考:www.jianshu.com/p/5d9e0d664…

这里是y轴标签,所以在  yAxis里设置 
yAxis: [{
              triggerEvent:true
          }],
  chart.on('mouseover',  function (params) {
        //标签名字显示在value
        //柱子显示在name
          console.log(params.name||params.value);
      });

简单的地图绘制

案例: 不知道是干嘛的字段,删掉再看看是什么地方没了就知道是干嘛的了 或者稍微改一下,对比一下

echarts.apache.org/examples/zh… www.makeapie.com/editor.html…

#template
<div @click="changeMap('map')" v-show="nowShow=='map'" id="littleMap" style='width:5rem;height:258px;cursor:pointer'></div>
#mounted
let guangdongJson = require('./guangdong.json') //放<script>
let chart = this.$echarts.init(document.getElementById("littleMap"));
    chart.hideLoading();
    this.$echarts.registerMap("guangdong", guangdongJson);
    chart.setOption({
          // backgroundColor: "#404a59",
    geo: {
        map: 'guangdong',
        show: true,
        roam: false,
        label: {
            emphasis: {
                show: false
            }
        },
        layoutSize: "100%",
        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(147, 235, 248, 0)", // 0% 处的颜色
                    },
                    {
                      offset: 1,
                      color: "rgba(147, 235, 248, .2)", // 100% 处的颜色
                    },
                  ],
                  globalCoord: false, // 缺省为 false
                },
                shadowColor: "rgba(128, 217, 248, 1)",
                // shadowColor: 'rgba(255, 255, 255, 1)',
                shadowOffsetX: -2,
                shadowOffsetY: 2,
                shadowBlur: 10,
              },
        }
    },
             series: [{
        type: 'map',
        map: 'guangdong',
        // aspectScale: 0.75,
        label: {
            normal: {
                show: false,
            },
            emphasis: {
                show: false,
            }
        },
        itemStyle: {
            normal: {
                areaColor: {
                    x: 0,
                    y: 0,
                    x2: 0,
                    y2: 1,
                    colorStops: [{
                        offset: 0,
                        color: '#073684' // 0% 处的颜色
                    }, {
                        offset: 1,
                        color: '#061E3D' // 100% 处的颜色
                    }],
                },
                borderColor: '#215495',
                borderWidth: 1,
            },
        },  
    }, ]
})

翻牌效果

<NumberCard :countStr="serverCount"></NumberCard>
#NumberCard.vue
<template>
  <div class="demo">
    <ul class="fp-box">
      <!-- 默认进来是7位,超过自动加 -->
      <li
        ref="li"
        v-for="i in countStr.toString().length"
        :key="i"
      >
        <!-- 每列中的10行数字 -->
        <span v-for="num in 10" :key="num">
          <span class="line"></span>
          <!-- {{ num - 1 }} -->
          <span class="num-wrap">{{ num - 1 }}</span>
        </span>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
   props: {
     countStr: Number,
   },
  data() {
    return {
      numberArr: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], //固定每列中的19行数字
      numStr: "", // 需要展示的数字字符串
      numArr: [0, 0, 0, 0, 0, 0, 0], //默认展示7个数字数组
      // countStr: "", // 需要展示的数字
    };
  },
  mounted() {
  	//this.countStr = "1132";
  	this.initNumCard();
  },
  watch:{
      countStr(){
          this.initNumCard()
      }
  },
  methods: {
    // 初始化数字卡片
    initNumCard() {
      this.numStr = this.countStr.toString();
      this.numArr = this.numStr.split("");
      let numArrlen = this.numArr.length;
      // 展示数字的处理,不够7位前面补0
      // 默认进来是7位,超过自动加
      this.$refs.li.forEach((item, index) => {
        let ty = this.numArr[index];
        // 滚动数字(li标签)
        item.style.transform = `translateY(-${ty * 47}px)`;
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.fp-box {
  display: flex;
  overflow: hidden;
  li {
    width: 30px;
    height: 47px;
    flex-direction: column;
    transition: transform 1s ease-in-out;
    margin-right: 4px;
    & > span {
      text-align: center;
      font-size: 24px;
      color: #3de7c9;;
      display: flex;
      display: inline-block;
      width: 30px;
      height: 47px;
      line-height: 47px;
      position: relative;
    //   .line {
    //     display: inline-block;
    //     height: 1px;
    //     background: #001347;
    //     width: 100%;
    //     position: absolute;
    //     left: 0;
    //     top: 23px;
    //   }
    }
  }
}
</style>

参考:www.jianshu.com/p/1441dc217…

柱形图定时切换

#切换很简单,这个柱形图是个组件,只要我传入的props数据改变,就会相应的变化
<customBottomRightChart :type="switchName"/>
#柱形组件
<template>
  <div>
    <div id="bottomRightChart" style="height: 4.4rem"></div>
  </div>
</template>
<script>
export default {
  props:["type"],
  mounted() {
    this.draw();
  },
  watch:{
      type(vlue){//这里保险一点
          console.log(vlue)
          this.draw()
      }
  },
  computed:{
  },
  mixins: [echartMixins],
  methods: {
    draw() {
      // 基于准备好的dom,初始化echarts实例
      this.chart = this.$echarts.init(
        document.getElementById("bottomRightChart")
      );
      this.chart.setOption(option1);
      if(this.type=='上传'){
        this.chart.setOption(option1);
      }else  if(this.type=='浏览'){
        this.chart.setOption(option2);
      }else  if(this.type=='计算'){
        this.chart.setOption(option3);
      }
    },
  },
};
</script>
#父组件
<template>
  <div id="bottomRight" @mouseover="stopInterval" @mouseout="intervalChart">//鼠标移入就清除定时切换,移出时再次设置定时切换
    <div class="bg-color-black">
      <div class="d-flex pt-2 pl-2" style='justify-content:space-between'>
        <div class="d-flex">
          <span style="color:#5cd9e8">
          <icon name="chart-area"></icon>
        </span>
        <div class="d-flex">
          <span class="fs-xl text mx-2">历史数据 共{{total}}次</span>
        </div>
        </div>
        <p style='color:grey;font-size:0.2rem'> 
        <span :class="{ active: switchName=='上传'}" style="cursor:pointer;border-right:1px solid white;padding-right:4px" @click="select('上传')"> 上传</span>
        <span :class="{ active: switchName=='浏览'}" style="cursor:pointer;border-right:1px solid white;padding-right:4px" @click="select('浏览')"> 浏览</span>
        <span :class="{ active: switchName=='计算'}" style="cursor:pointer" @click="select('计算')"> 计算</span>
        </p>
      </div>
      <div >
      <!-- <div style="margin-top:0.3rem;margin-bottom:0.3rem"> -->
        <customBottomRightChart :type="switchName"/>
      </div>
    </div>
  </div>
</template>

<script>
import customBottomRightChart from "@/components/echart/bottom/customBottomRightChart";
export default {
  data() {
    return {
      total:0,
      switchName:'上传',
      interval:null
    };
  },
  components: {
    customBottomRightChart
  },
  mounted() {
    this.total = this.$store.state.res?.dataShareCount
    this.intervalChart();
  },
  methods: {
    select(name){//手动切换
      this.switchName = name;
      if(this.switchName == '上传'){
        this.total = this.$store.state.res?.dataShareCount
      } else if(this.switchName == '浏览'){
        this.total = this.$store.state.res?.dataBrowseCount
      } else if(this.switchName == '计算'){
        this.total = this.$store.state.res?.calculateDataCount
      } 
    },
    stopInterval(){//清除切换
      clearInterval(this.interval);
    },
    intervalChart(){//定时切换
      this.interval = setInterval(()=>{
        if(this.switchName == '上传'){
          this.switchName = '浏览'
        } else if(this.switchName == '浏览'){
          this.switchName = '计算'
        } else if(this.switchName == '计算'){
          this.switchName = '上传'
        } 
      },2000)
    }
  }
};
</script>

默认全屏

全屏只能由用户主动触发,程序设置的自动全屏会被阻挡

可以用按钮来提示用户点击触发全屏

template
      <div
        style="position: fixed; top: 0%; left: 30%; z-index: 500"
        @click="f11"
      >
        点击全屏显示
      </div>
methods:{
   f11() {
      console.log("f11");
      function requestFullScreen(element) {
        var requestMethod =
          element.requestFullScreen ||
          element.webkitRequestFullScreen ||
          element.mozRequestFullScreen ||
          element.msRequestFullScreen;
        if (requestMethod) {
          requestMethod.call(element);
        } else if (typeof window.ActiveXObject !== "undefined") {
          var wscript = new ActiveXObject("WScript.Shell");
          if (wscript !== null) {
            wscript.SendKeys("{F11}");
            wscript.SendKeys("{F5}");
          }
        }
      }
      //默认全屏显示
      var elem = document.getElementsByTagName("html")[0];
      requestFullScreen(elem);
    },
}

不过按刷新会退出全屏,很无奈,我的需要全屏后还需要刷新来让元素适应屏幕,不然就需要对元素一个一个进行width100,height100的设置,所以我就放弃了,诶。。

遇到的一些问题

  • 有碰到后端同学帮我打包的弄上服务器后,找不到资源的情况 此时把history改为hash即可
  • 由于没有用webpack生成html,此时的title是package.json的name,又换不成中文 此时就把打包生成的html里的title改了就好