从flexible.js引入高德地图谈起的移动端适配
曾几何时,前端还仅仅是PC端的。随着移动时代的兴起,h5及css3的推陈出新。前端的领域慢慢的由传统的pc端转入了移动端,这也导致了前端这一职业在风口的一段时间出尽了风头。
从手写不同尺寸的媒体查询css到以手淘的flexible.js来进行移动端的适配,虽然过程曲折,不过效果也是十分的显著,因为有了成熟的体系以后,什么东西就有据可寻,适配也就没那么困难了。
但是,因为这次引入了高德地图,所以在适配上出现了一点意料之外的问题。
首先,我要说下视口这个东西,因为手淘的这个方案是严重依赖视口这个概念的。
1. 视口
1.1 视口的分类
ppk将视口分为三大类:布局视口、可视视口、理想视口。
那视口是什么呢?通俗点说就是浏览器上(也可能是一个app中的webview)用来显示网页的那部分区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览器的可视区域要大,因为为了正常的显示PC端的网页,浏览器会将自己的layout viewport设置为一个较大的值,结果就是会出现左右的滚动条。
布局视口和可视视口我们作基本了解即可。在实际工作中,我们需要接触和处理的更多是ideal viewport。
而我们前端一直孜孜以求的移动端的适配,其实就是为了让用户的浏览器中呈现的是我们的理想视口。
ideal viewport并没有一个固定的尺寸,不同的设备拥有不同的ideal viewport。早期移动端开发,对于终端设备适配问题只属于Android系列,有320pt的,有360pt的,有384pt的等等。但随着iPhone6、iPhone6+的出现,从此终端适配问题不再是Android系列了,也从这个时候让移动端适配全面进入到”杂屏”时代。
http://viewportsizes.com 里面收集了众多设备的理想宽度。
1.2 如何影响视口?
既然viewport这么重要,那我们怎么去控制他为我所用呢?这个时候,就轮到meta标签出场了。
1 | <meta |
content里面的属性说明:
| 属性 | 说明 |
|---|---|
| width | 设置 layout viewport 的宽度,为正整数或字符串 device-width |
| height | 设置 layout viewport 的高度,几乎不使用 |
| initial-scale | 设置页面的初始缩放值,相对于 ideal viewport 进行缩放 |
| minimum-scale | 允许用户的最小缩放值 |
| maximum-scale | 允许用户的最大缩放值 |
| user-scalable | 是否允许用户进行缩放,no 或 yes |
1 | <!-- 将 layout viewport => ideal viewport --> |
上面两种方式是殊途同归的。那么,为什么我们还要将两个都写上去呢?
initial-scale=1.0:处理在 iPhone、iPad 上,无论竖屏还是横屏,宽度都是竖屏时 ideal viewport 宽度的问题。width=device-width:处理在 Windows Phone 上的 IE 无论竖屏还是横屏都把宽度设为竖屏时 ideal viewport 宽度的问题。
1 | <meta name="viewport" content="width=400, initial-scale=1.0" /> |
如果出现了上面这种冲突,浏览器会取两者中较大的那个值。总结起来就是”谁大谁先行”。
2. 引入高德后页面的表现
在vue的spa项目中引入高德以后,我们发现在不同的dpr下,地图的显示效果差距非常大。
在dpr=3的时候,也就是plus的机型上,地图显得格外的小,几乎用肉眼是无法看清上面的字体。所以,基于flexible的适配方法肯定是有问题的了。
而出现这个问题的原因就是我们的viewport被缩放了。
1 | if (!dpr && !scale) { |
通过上面的代码计算出了viewport缩放的比率。当处于iPhone 6+ Plus的时候,scale = 0.3333...
1 | metaEl.setAttribute( |
最后写到页面上面的结果就是:
1 | <meta |
所以,iPhone Plus是414pt,通过flexible将viewport缩小了0.333…,414 / 0.333... = 1242,而正好高德地图通过canvas绘制的画布宽度也就是1242。
3. 如何解决这个问题
处理这个问题的方法大致有三种。
3.1 通过vue-router的路由守卫进行处理
1 | beforeMount() { |
不过这样的方式不是很好,因为页面在过渡的时候会出现一瞬间样式的变形。而且如果在当前有地图的页面有其他结构的话,其他结构也会错乱。
Tips:如果不是SPA的应用,而且整屏页面是地图占满的情况下,这个方案还是可行的。
3.2 通过css scale属性
这个方法在试验了以后,也存在问题。虽然地图的大小是正常了,但是在地图上进行点标记的时候,会出现地图位置的偏移。
Tips:如果仅仅是展示,而并没有任何交互的情况下,这个方式也是可行的。
3.3 通过设置dpr=1(推荐)
通过设置dpr=1,强制flexible布局对viewport不进行缩放。
1 | <meta name="flexible" content="initial-dpr=1" /> |
这样,最后写到页面上的meta标签就是:
1 | <meta |
既然viewport没有缩放了,高德地图通过canvas绘制的地图也就是按照我们的ideal viewport来进行处理了。
不过这种方式会产生另外两个副作用:
- 通过缩放来处理的”1px问题”需要重新去处理
- 通过dpr设置的不同dpr下的文本字号大小,可能会出现13px这样很奇葩的尺寸
4. 结尾
大漠对于这个问题的解释是:flexible已经完成自己的使命,该功成身退了。他推荐使用vw、vh标准的新布局方式。
而到底用不用这套方案,作为前端的我们也是见仁见智了!