js

前端开发地图应用的调研

我司的产品终于发布了新版本,所以忙碌的开发暂时告一段落。最近在做下一期的规划,然后就是要做前端网站来满足用户的需求。由于我们的产品是和地图强相关的,所以也对地图做了很多调研。

# 基本需求

产品需要在国内和国外使用,费用合理,可以换地图的贴图并且能在地图上绘制各种信息。例如多边形或圆形还有贝塞尔曲线。

# MapKit JS

苹果居然也出了网页版本的地图产品MapKit JS,可谓是良心。但是目前还处于 Beta 版本。如果以后要考虑产品的全平台化,显然不是一个很好的选择。不过苹果的产品可以在国内国外使用不用太担心地图偏移问题,而且可以贴图和绘制图形,但是目前网页版还不能绘制贝塞尔曲线,iOS 客户端倒是可以。

# MapBox

MapBox 是一个地图服务提供商,经过调研 MapBox 使用最新的 WebGL 技术来渲染,摆脱了传统的下 tile 来贴图的方式,渲染速度得到了大大的提升。也能解决国内和国外的地图显示问题,但是画图功能就只有画线和多边形。不过提供了底层的画图层的接口,需要自己写 WebGL 的 shader。这就增加了开发成本。。。

# GoogleMap

谷歌地图当然好,但是我最后才说。因为谷歌无法在国内使用,这种情况下我就不得不写两套接口来对应,例如国内高德地图,国外谷歌地图,会大大增加开发成本。而且谷歌地图最近刚升级付费条款,费用是按照请求次数来收,所以用户大量增长之后的开销也会非常大。不过谷歌也不能画贝塞尔曲线。。。

# 地理坐标系

由于是需要在地图上绘制新的 tiles,所以自然就涉及到坐标的转换和计算。如何计算一个经纬度落在哪一张 tiles 上,以及在不同缩放级别下 tiles 的正常显示和重绘。这些都是需要自己来实现的。 这里有一个还算有名的官方介绍,并给出了 Python 的源码。可以参考这个来进行实现。

# 坐标系转换

每个国家都有自己的坐标系系统,虽然 GPS 使用的WGS 84标准非常流行,但是这个是美国制定的。每个国家当然都需要根据自己国家需要来定制自己的标准。例如中国就有北京 54 坐标系,西安 80 坐标系。北京 54 和西安 80 是参心坐标系,大地原点分别在苏联和西安。难以表达高度信息,目前国家正在推广2000 国家大地坐标系,这个和 WGS84 一样是地心坐标系,即以地球质量中心为原点。日本也有自己的平面直角坐标系,我们当然需要各种坐标转换,还好有现成的开源项目proj4js

# 总结

各个地图服务商都各有优劣,但却没有一款完美的。主要是用途也比较特殊,可能在地图服务上进行二次开发的可能性比较高吧。不过提供地图服务的也没几家可以选择的。。。

如何封装第三方vue组件

终于算是正式接触 SPA 的前端工作了,最近在解决很多 Vue 组件的问题,其中就有一个针对第三方组件的定制化需求,花了不少时间来折腾。

# 解决 v-model 绑定

这次封装的就是 element 的前端 vue 框架,因为框架本身对 IOS 兼容性不好,所以需要二次封装。封装的是一个 select 组件。所以需要数据的双向绑定,官方教程也已经解释了。 v-model 本质上就是绑定一个值和监听相应的事件。 这次本质是封装的一个 input 元素,所以我们需要手动绑定 value 和监听事件。

<template>
  <el-select v-bind:value="value" v-on="$listeners"></el-select>
</template>
1
2
3

官方文档也解释了这个内置变量的用法vm-listeners

# 继承父元素的属性

父元素的属性继承可以使用v-bind="$attrs"来完成。所以完成组建的透明封装只需要加上三个指令。

<template>
  <el-select v-bind="$attrs" v-bind:value="value" v-on="$listeners">
  </el-select>
</template>
1
2
3
4

虽然知道答案之后很简单,但是探索的过程中还是比较花时间的。希望能帮助大家解决这个问题,如果有什么疏漏之处,也请大家指正。

JavaScript开发中的性能优化

最近工作比较清闲,5 月又换了一个工作环境。总结下最近看的有关 JavaScript 性能的知识,并记下来供未来的自己参考。希望自己能不忘初心,继续成长!

# 使用 requestAnimationFrame 来更新动画

使用requestAnimationFrame把动画渲染交给浏览器,可以保证渲染保持在 60FPS。应该避免使用setTimeout或者setInterval来实现动画,因为计时器和事件队列会消耗更多的资源,还会导致无用的页面重新绘制。

# 使用 Web Workers 来进行复杂的运算

可以把单纯的计算放在 Web Workers 中,这样不影响主页面的渲染和流畅,例如加密和矩阵变换的运算就可以完全放在 Web Workers 中来减少主线程的执行时间,避免浏览器渲染堵塞。

# 避免微优化 JavaScript

举个最简单的例子,我曾经在一本书上看到过一个提升程序效率的例子。大致是这样的:

var array = [1, 2, 3, ...100];

for (var i = 0; i < array.length; i++) {
  console.log(array[i]);
}
1
2
3
4
5

这里的array.length获取数组的长度,每次都要计算数组长度会消耗不少时间,优化之后的代码是这样的:

var array = [1, 2, 3, ...100];
var len = array.length;
for (var i = 0; i < len; i++) {
  console.log(array[i]);
}
1
2
3
4
5

通过缓存数组的长度来保证只计算一次。这就是典型的微优化,说实话这段代码我一直在用,直到最近读了其他的书才发现,现在的 JS 解释器早就优化了对数组长度的计算。无论是读取一次还是一万次消耗的时间都没有太大差别。微优化应该是 JS 引擎需要做的事情,我们不应该在实际开发中在这方面耗费过多的时间。

# 滑动事件优化

当用户监听滑动事件并执行相关动画操作的时候,记得使用window.requestAnimationFrame来优化动画的执行。

function onScroll(evt) {
  // Prevent multiple rAF callbacks.
  if (scheduledAnimationFrame) return;

  scheduledAnimationFrame = true;
  requestAnimationFrame(readAndUpdatePage);
}

function readAndUpdatePage() {
  // do something
  requestAnimationFrame(readAndUpdatePage);
}

window.addEventListener('scroll', onScroll);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

参考:

Debounce Your Input Handlers

Optimize JavaScript Execution