Safari难道是下一个IE?兼容性这么“差”

最近被 Safari “玩”了一把,为了适配它,做了不少的工作。Safari 在Canvas 上确实留了一手,让我们不得不妨,不过正因为有了 Safari 的限制才能够让我的程序更优,占用更少的内存空间。

Safari 在实现 Canvas 时对内存进行了限制,在不同设备上允许使用的内存不同,具体根据你设备 RAM 的大小计算。当你使用 Canvas 时占用的内存超过限制时会提示:

212cab99ca43c17722679af37b8b9482.png

一但超出限制,使用 getContext('2d') 将会返回 null。但我们不知道 Safari 是如何计算 Canvas 占用的内存空间的。

这就不得不够从源码中找答案,翻开 webkit 的源码(如果你不知道如何查看 webkit 的源码,可以看这篇文章,阅读量已有 8000+)

简看 Canvas 源码,突发奇想

按提示,直接在源码中搜索相关内容:

8912505dadb67e2dde00c696d6987e7c.png

从源码中可以看到 Canvas 的内存占用空间为 4 * width * height,允许使用的最大内存空间由 maxActivePixelMemory 这个函数计算,这个函数计算规则如下:

187a284c0c0024cbbd7dffce2a634645.png

可能你会好奇为啥计算画布的内存空间公式 4 * width * height有个 4,代表什么意思?

想一下画布的本质是什么?比如我在画布上写下 SY 时,它的 data 是什么样的?

我创建一块画布,然后写下 S、Y这两个字母,并打印 imageData

ba86e03565704f6348f60b65911a8374.png

图中返回的数组长度为 4096 = 4 * 32 * 32

25ccb51ca5e85d6cbf2036d43a5de418.png

看下 data 中具体的值,因为 S、Y 两个字符绘制时发生了重叠,你看到的数值不是 RGB 对应的值。

f80a50294e6fd371fab3173a3af68083.png

字母在画布中的本质其实是色值,4 表示 RGBA 的具体内容,这就是 4 的来源。

问题来了,有时候不得不创建很多 Canvas,如何才能够避免内存限制,比如实现 2000页的这种文档,每页内容都由 Canvas 绘制:

3fccdbcd7c9fe85a2561371ddb15b3c2.png

难道要创建2000个Canvas?

当然不能这样,需要采用一定的优化策略,比如只绘制可视区域的内容,不可见的部分不进行绘制。当页面即将出现时再进行绘制。这就涉及到一个问题,已经渲染后的内容如何让其释放内存空间。

以前想过通过 clearRect 清除画布中的内容,这种想法可笑至极,即使清空了内容,只要画布还在,内存空间就不会被释放。

也可以把 Canvas 这个元素从 DOM 中删除,来释放内存空间。这样会频繁操作 DOM。

还有一种方法,可以设置 CanvasElement 的 width 和 height 为 0,设置这两个值后画布上内的内容会被清空,内存空间也会被释放。

到这里,只要能够监听每页出现即可,可以直接使用 IntersectionObserver 这个 API,它是异步的,不会卡主线程,相比以前监听滚动事件计算可视区域的元素,更优秀,但是不兼容 IE,好在官方提供了 polyfill 来解决这个问题。详细地址:

https://github.com/w3c/IntersectionObserver/blob/main/polyfill/intersection-observer.js

使用 IntersectionObserver 后我们即可在元素出现时设置 Canvas 的宽度,并进行绘制。

详细代码如下所示:

733ebee50a4a87a64dd7d73a8329e482.png

96708e2ed3e2cfdde4c901137d11ca67.png

可能有人会担心每次页面出现时渲染会不会很卡,如果绘制的内容比较少,可以忽略不记。比如每页绘制 4000 个文字,感受不到卡顿,当然在绘制过程中可根据实际情况进行优化。

到此,即使存在2000页也不会消耗很大的内存,相比之前内存空间可节约 90%。

说到这里,不得不提 Safari 还有一个限制,就是它的画布大小有限制,不过其它浏览器也会有限制,所以在创建画布的时候,需要留意画布不要太大。从下面的源码中看到,在 iOS 设备上画布会更小。

139886edb1ce323c80e5b49cf0d83518.png

前几天,我还踩过个坑:留意 drawImage 的坑,Canvas教程大升级

最后再说一件事,前段时间把 Canvas 的教程升级了,内容还在撰写中。效果如下:

20785a145e5b2f46973a072be5fee294.png


大家加油!!!

demo地址:https://github.com/lefex/FE/tree/master/learn-canvas

152b47bd3160ee4ed5087669822f4fba.png

长按关注

素燕《前端小课》

帮助 10W 人入门并进阶前端

官网:https://lefex.gitee.io/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值