[极致用户体验] 微信设置大字号后,iOS 加载网页时闪动怎么办?
我是 HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,发送加微信,交个朋友),转发本文前需获得作者 HullQin 授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加 Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。
背景
之前的文章,我提到网页开发的一个常见问题:《在微信大字号模式下,网页样式乱了怎么办?》。上文中提供了一种解决方案,在用户调整微信字体大小后,可以保证网页字体大小不变,解决了样式错乱的问题。
但是上面的解决方案,背离了微信「关怀模式」和「大字号模式」的初衷。所以我又写了一篇文章:《让你的网页,适配微信大字号模式!体验超好,快来收藏》,介绍了几种方案,助你网页适配微信的大字号。
但是在 iOS 操作系统下(iPhone 或 iPad),仍然有个问题。如果用户之前设置了网页的大字号,进入任意网页时,就有个明显的闪动:
但是在安卓,没有这个问题,会直接以大字号展示。
分析原因
这与微信大字号的实现方式有关。而实现方式又与机型有关。包括以下 3 种:
安卓
在安卓,网页不会闪动,是因为安卓使用setTextZoom设置字体比例。早在 html 加载前,就已经设置好了,它也无需修改 dom。
后续用户修改网页字号时,只需要安卓调用setTextZoom
即可(这是微信客户端实现的,我们 Web 开发者无需关注)。
iPhone
iPhone 闪动,是因为它必须等到 html 加载完,渲染页面的 JS 也执行完,再给body
标签添加text-size-adjust这个 CSS 样式(它需要修改 dom)。
后续用户修改网页字号时,只需修改body
的text-size-adjust
这个 CSS 样式即可(这是微信客户端实现的,我们 Web 开发者无需关注)。
解决思路
如果我们能知道用户设置的缩放比例,在我们的 JS 主动给body
标签添加text-size-adjust)这个 CSS 样式(在渲染之前就添加),那么闪动的问题就解决了。
iPad
我今天研究了一下,发现微信 iPad 大字号和 iPhone 大字号,实现方式居然不一样!
iPad 闪动,是因为它必须等到 html 加载完,渲染页面的 JS 也执行完,再给所有包含 Text 文本的标签添加style
属性,里面直接指定了计算后的font-size
。当然,网页元素的原始字号大小保存在了元素的属性mp-original-font-size
里。
动态赋值后,你的 DOM 结构会变成这样:
后续用户修改字体时,会根据mp-original-font-size
和放大比例,重新计算所有元素的font-size
,并动态设置所有元素的style
中的font-size
。
可能有朋友要问了:一次性设置这么多style
属性,这不会很卡吗?
没错,是很卡,在安卓、iPhone、iPad 上设置大字号,就 iPad 最卡!
解决思路
如果我们能知道用户设置的缩放比例,在我们的 JS 主动给所有的包含 Text 的元素添加font-size
这个 CSS 样式(在渲染之前就添加),那么闪动的问题就解决了。
开发代码,解决问题
我通过神秘方式,获取了一串神秘代码:JSON.parse(window.__wxWebEnv.getEnv()).fontScale
,在微信内置浏览器中,执行这个方法,是可以获得用户设置的缩放大小的。当然,你必须先引用「微信JS SDK」,才能用这个代码,否则会报错,建议结合 try catch 使用它。
需要在 html 文件 head 引入:
下面针对 iPhone 和 iPad 这 2 种机型,分别给出解决方案。
iPhone
思路介绍:给 body 设置一个-webkit-text-size-adjust
样式,按照字号缩放比例设置即可。
iPad
思路介绍:
通过 user agent 判断浏览器类型和机型。如果发现是微信浏览器,且是 iPad,那么就执行本段代码,调整初始字号。
如果当前用户字号
fontScale
为 1,无需缩放,直接结束函数。如果当前用户字号
fontScale
不是 1,就先把整个body
隐藏,并继续以下步骤。从
body
开始,递归遍历子节点,设置所有的mp-original-font-size
。从
body
开始,递归遍历子节点,设置所有的style
里的font-size
,是根据mp-original-font-size
乘以fontScale
计算出来的。全部赋值后,再把
body
展示出来。至此,初始字号设置完毕,画面不再闪现。
判断机型,执行相应函数
补充说明
如何实现:按需引入微信 JS SDK?
如果用户不是使用的微信浏览器,那么完全没有必要引入微信 JS SDK。
你可以先判断 user agent,再动态引入:
这样,在回调函数中,可以获取fontScale
。但是为了解决闪动问题,你可能需要在document.createElement('script')
前,先把body
隐藏(document.body.style.display='none'
)。
iPad 的字号缩放方式有办法跟 iPhone 统一吗?
还真有。
只要我们设置了这个变量:
那么在 iPad 中,缩放字号,也会通过-webkit-text-size-adjust
方式来缩放了。只是存在兼容性问题,一些 iPad 不支持这个样式,用户就无法通过微信控制字号了。
此时,整个解决方案是最简洁的:
如果你还希望按需引入微信 JS SDK,再做一些容错处理,整个逻辑就是这样子:
我就是用了这个方式,亲测有效。你可以点开我的网站 game.hullqin.cn 体验一下。
写在最后
我是 HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,发送加微信,交个朋友),转发本文前需获得作者 HullQin 授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加 Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。
版权声明: 本文为 InfoQ 作者【HullQin】的原创文章。
原文链接:【http://xie.infoq.cn/article/cfc3b798cde1b64596e6cec67】。文章转载请联系作者。
评论