数据大屏开发

298 阅读8分钟

中交信捷数据大屏前端开发经验总结分享

!!! 所有数据均为假数据, 不具有参考价值

!!! 所有数据均为假数据, 不具有参考价值

!!! 所有数据均为假数据, 不具有参考价值

1. 成果

image.png

image.png

image.png

image.png

image.png

2. 项目结构

  • 先进行项目需求分析,主页面有6个大屏显示,且中间的地图一直是固定的.决定使用动态组件,切换其他模块方式实现效果

  • image20220721141038700.png

  • 简单说下每个文件夹作用

    assets // 存放静态文件,图片.公用的css样式, 字体font, 证书说明, 外部js文件(舍弃了,没用到)
    components // 公共组件, 例如: 整个项目包裹在scalebox组件内, 使其按照比例1902 * 1080 展示, 数字增长组件, 增长下降趋势组件, echarts组件等。
    const // 静态常量, 枚举, 省市的地图坐标
    pages // 显示区域,包含每一屏的代码.
     - main-grid-components.js 原因: 项目使用的是组件切换.main.vue需要引入的组件过多.使其页面臃肿.直接单独管理组件引入,方便读写防止混淆代码.
    utils // 工具函数, 包括3D饼图的封装的函数, 地图geoJSON文件, 坐标偏移的工具函数等
    service // service内容和每个模块(每个屏幕),相对应,请求函数的封装,页面直接使用,跨页面调用接口不需要重复写.统一的httpService服务可以处理大的需求变更等
    router // 普通的路由文件, 没多少内容.
    

image20220721112726173.png

3. 问题总结

  • 大量散点图绘制问题

    • 技术预研: 最开始选了3d地图,方向错误,浪费了些时间
    • 实现过程: 下载案例.放到自己的项目中并跑起来,效果无误.
    • 真实数据: 拿到真实数据之后绘制,后端给网格处理后的数据.导致绘制的样子很奇怪.分割线非常明显
    • image.png
    • 重复点问题: 手动拉平数据.添加blendMode: lighter 属性, 达到效果图
    • 文档解释: blendMode: 'lighter' 也是比较常见的一种混合模式,该模式下图形数量集中的区域会颜色叠加成高亮度的颜色(白色)。常常能起到突出该区域的效果。
  • 快速切换地图, 导致下一个页面会出现重复的点问题(惨状如下)

    • image20220721113502649.png

    • 问题原因: 快速切换时,地图实例没有切换.chart.appendData仍在执行过程中,并且找到了第二个地图配置项对应的seriesIndex进行继续绘制.

    • 解决方法. 开始尝试 切换时清空地图, 销毁实例等方法,均无效过. 后面想到chart.appendData函数会有个seriesIndex 参数,把执行比较慢的,series数组多放几组数据, seriesIndex 在别的页面找不到,就会报错. trycatch抓下错误即可. 同时切换做个防抖.200ms内不能连续切换.

    • 反思: 当时毕老师还提了一种方法.把地图归类到各个页面.(目前实现.大屏切换.地图是不动的).应该也可以解决此类问题.但是成本过高.可能会来不及.

      还有一种方法是指定seriesIndex , 和现在实现效果类似. 或者是还有更好的方法.暂时没想到

  • 影响项目进度的,但是必须做的问题(演示版本,需要看到效果.).直接展示pag文件

    • async loadPagFile(url) {
          const promise = new Promise((resolve, reject) => {
              PAGInit()
                  .then((PAG) => {
                      fetch(url).then((response) => response.blob()).then(async (blob) => {
                              const file = new window.File([blob],url.replace(/(.*\/)*([^.]+)/i, "$2"));
                              this.pagFile = await PAG.PAGFile.load(file);
                              document.getElementById("pag").width = this.pagFile.width();
                              document.getElementById("pag").height = this.pagFile.height();
                              const pagView = await PAG.PAGView.init(this.pagFile, "#pag");
                              pagView.setRepeatCount(0);
                              resolve(pagView);
                          });
                  })
                  .catch((err) => {
                      reject(err);
                  });
          });
      
          return promise;
      },
          
      // this.pagView = await this.loadPagFile("./map.pag");
      // setProgress
      
    • 有个有趣的点, 需要重复pag动画后半部分,但是根据现有的api实现不了. 定时器, 设置开始进度(从什么时候开始播放)解决

  • geoJSON文件获取问题.展示效果和设计稿不符(南海诸岛隐藏的效果)

    • 1.先通过echarts配置解决
      regions: [
        {
          name: "南海诸岛",
          itemStyle: {
            opacity: 0, // 设置透明度隐藏
            label: {
              show: false,
            },
          },
        },
      ],
      
    • 2: 障眼法解决

    • image20220721135351239.png

    • 使用绝对定位, 相同背景色遮盖多余的点

    • image20220721143811398.png

  • 坐标点整体偏移, 客户提供的经纬度是 gcj-02的, 项目使用的是echarts的百度地图bd-09 坐标系

    • GCJ02相当于是一个保密算法的偏移量。然后所有大陆被绘制的民用地图(矢量图)都需要在WGS84的基础上加上这个偏移量。

    • 1、地理坐标系与投影坐标系

      地理坐标系也就是球面坐标系,是将本不是椭球体的地球进行椭球体化,从而形成球面坐标体系,国际标准的地理坐标系就是WGS-84坐标系;

      只不过各个国家为了反映该国家所在区域地球的真实形状,采用不同的数学模型对地球进行椭球体化,所以就有个Beijing54、Xian80坐标系。

      投影坐标系是为平面坐标,是将地理坐标根据一定的投影规则投影到平面,形成的平面直角坐标系,比如高斯-克吕格投影,墨卡托投影等。

      2、WGS-84坐标系

      WGS-84坐标是地理坐标系,也就是GPS坐标,一般用国际标准的GPS记录仪记录下来的坐标,都是GPS的坐标。但是在中国为了保密,任何一个地图产品都不允许使用GPS坐标。GPS坐标以度分秒形式表示经纬度,比如google earth上采集到的是39 31’20.51,那么应该这样换算,31分就是31/60度,20.51秒就是20.51/3600度,结果就是39+ 31/60 + 20.51/3600 度。

      3、GCJ-02坐标系 与 百度 bd-09坐标系

      GCJ-02坐标系又名 火星坐标系 ,是我国国测局独创的坐标体系,由WGS-84加密而成,在国内,必须至少使用GCJ-02坐标系,或者使用在GCJ-02加密后再进行加密的坐标系,如百度坐标系。高德和Google在国内都是使用GCJ-02坐标系,可以说,GCJ-02是国内最广泛使用的坐标系。

      百度坐标系是在GCJ-02坐标系的基础上再次加密偏移后形成的坐标系,只适用于百度地图。(当然,百度地图api接口提供了google坐标转百度坐标、原始坐标转百度坐标的接口,网上也有一些转换算法,个人建议还是用百度地图api比较准确)

      4、WGS84 Web Mercator 坐标系

      我们在做开发的时候,尤其是web地图开发,两种坐标系至关重要 WGS84(WKID:4326) 和 WGS84 Web Mercator (WKID:102113) 。WGS84 Web Mercator 是目前在线地图(平面)采用的通用坐标系,属于投影坐标系。

      5、测试

      测试方法:

      ①使用arcgis api for javascript 调用 Google卫星地图服务;

      ②在①的基础上调用arcgis api for javascript 绘制折现的工具,在卫星影像图中辨识并绘制一条道路,将其坐标点经纬度(这里输出的应该是GCJ-02火星坐标系吧?我不确定,有知道的望留言!)输出到控制台;

      ③使用高德地图API将②获取到的坐标点集绘制成折线,比较从Google地图中获取到的点集坐标在高德地图中是否有偏差?

      ④使用百度地图API将②获取到的坐标点集绘制成折线,比较从Google地图中获取到的点集坐标在百度地图中是否有偏差?

  • 不同分辨率显示器导致绘制散点图的效果不一致 例: windows和mac - image20220719142236570.png

  • image20220719142310853.png

  • 解决方案: init的时候 修改入参配置 将 devicePixelRatio改为1. 但是没生效.

  • 这里发现了echarts的一个bug.(大家有其他见解的请联系我~)

    // echarts.js 源码
    var Env = (function () {
        function Env() {
            this.browser = new Browser();
            this.node = false;
            this.wxa = false;
            this.worker = false;
            this.svgSupported = false;
            this.touchEventsSupported = false;
            this.pointerEventsSupported = false;
            this.domSupported = false;
            this.transformSupported = false;
            this.transform3dSupported = false;
            this.hasGlobalWindow = typeof window !== 'undefined';
        }
        return Env;
    }());
    var env = new Env();
    
    if (env.hasGlobalWindow) {
    	// 这里用了Math.max 取了最大的一个,init的时候传参为1的时候.mac电脑(或者分辨率高的)默认值为2会导致1不生效
        dpr = Math.max(window.devicePixelRatio
            || (window.screen && window.screen.deviceXDPI / window.screen.logicalXDPI)
            || 1, 1);
    }
    var devicePixelRatio = dpr;
    
  • 所以项目中直接 修改比例 使 window.devicePixelRatio = 1 (可能会带来其他问题.但是解决了问题.可能就是解决了一个问题,埋了一个雷,不知道哪天炸吧). 主要是暂时没有想到其他更好的方法.

  • image20220721144518633.png

4. 不足点. 改进

  • 多花时间打磨第一屏,先改问题,不然回过头来,花的时间会成倍增长
  • 和后端联调约定的接口方案时,接受了他的方案.所有的接口名称统一,入参函数有区别,导致后面观察接口返回数据时比较痛苦.反思一下
  • 由于时间原因,过渡加载动画做的不足, 设计稿没达到更高的还原度.一些比较耗时的展示采取了降级处理

5. 经验心得