中交信捷数据大屏前端开发经验总结分享
!!! 所有数据均为假数据, 不具有参考价值
!!! 所有数据均为假数据, 不具有参考价值
!!! 所有数据均为假数据, 不具有参考价值
1. 成果
2. 项目结构
-
先进行项目需求分析,主页面有6个大屏显示,且中间的地图一直是固定的.决定使用动态组件,切换其他模块方式实现效果
-
-
简单说下每个文件夹作用
assets // 存放静态文件,图片.公用的css样式, 字体font, 证书说明, 外部js文件(舍弃了,没用到) components // 公共组件, 例如: 整个项目包裹在scalebox组件内, 使其按照比例1902 * 1080 展示, 数字增长组件, 增长下降趋势组件, echarts组件等。 const // 静态常量, 枚举, 省市的地图坐标 pages // 显示区域,包含每一屏的代码. - main-grid-components.js 原因: 项目使用的是组件切换.main.vue需要引入的组件过多.使其页面臃肿.直接单独管理组件引入,方便读写防止混淆代码. utils // 工具函数, 包括3D饼图的封装的函数, 地图geoJSON文件, 坐标偏移的工具函数等 service // service内容和每个模块(每个屏幕),相对应,请求函数的封装,页面直接使用,跨页面调用接口不需要重复写.统一的httpService服务可以处理大的需求变更等 router // 普通的路由文件, 没多少内容.
3. 问题总结
-
大量散点图绘制问题
- 技术预研: 最开始选了3d地图,方向错误,浪费了些时间
- 实现过程: 下载案例.放到自己的项目中并跑起来,效果无误.
- 真实数据: 拿到真实数据之后绘制,后端给网格处理后的数据.导致绘制的样子很奇怪.分割线非常明显
- 重复点问题: 手动拉平数据.添加blendMode: lighter 属性, 达到效果图
- 文档解释: blendMode: 'lighter' 也是比较常见的一种混合模式,该模式下图形数量集中的区域会颜色叠加成高亮度的颜色(白色)。常常能起到突出该区域的效果。
-
快速切换地图, 导致下一个页面会出现重复的点问题(惨状如下)
-
-
问题原因: 快速切换时,地图实例没有切换.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: 障眼法解决
-
-
使用绝对定位, 相同背景色遮盖多余的点
-
-
-
坐标点整体偏移, 客户提供的经纬度是 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 -
-
-
解决方案: 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 (可能会带来其他问题.但是解决了问题.可能就是解决了一个问题,埋了一个雷,不知道哪天炸吧). 主要是暂时没有想到其他更好的方法.
-
4. 不足点. 改进
- 多花时间打磨第一屏,先改问题,不然回过头来,花的时间会成倍增长
- 和后端联调约定的接口方案时,接受了他的方案.所有的接口名称统一,入参函数有区别,导致后面观察接口返回数据时比较痛苦.反思一下
- 由于时间原因,过渡加载动画做的不足, 设计稿没达到更高的还原度.一些比较耗时的展示采取了降级处理
5. 经验心得
- 图片可以通过 tinypng.com/ 进行压缩减少体积
- webpack可以配置tree-shaking删除死代码.减少打包体积.尤其是echarts全量引入配置之后,可以大大的减少体积
- echarts demo示例集合
- 各类坐标之间的相关梳理文档
- www.caotama.com/1841003.htm…
- blog.csdn.net/sinat_41310… // 各类坐标系的相关文章