canvas简介和常见性能优化
画布是一个矩形区域,你可以控制它的每一个像素。
Canvas有很多方法可以画出路径、矩形、圆形、字符和添加图像。
画布是逐像素渲染的。
在Canvas中,图形一旦被绘制,就不会继续吸引浏览器的注意力。如果它的位置改变,整个场景需要被重画,包括任何可能已经被图形覆盖的对象。
SVG基于XML,这意味着SVG DOM中的每个元素都是可用的。您可以将JavaScript事件处理程序附加到元素上。
在SVG中,每一个绘制的图形都被视为一个对象。如果SVG对象的属性发生变化,浏览器可以自动再现图形。
-取决于分辨率
-不支持事件处理程序。
-弱文本渲染能力
-结果图像可以保存在。png或者。jpg格式。
-最适合图像密集型游戏,其中许多对象需要频繁重绘。
-独立于分辨率
-支持事件处理程序
-最适合具有大渲染区域的应用程序(如谷歌地图)
-高复杂度会降低渲染速度(任何过度使用DOM的应用都不快)
-不适合游戏应用
我们在绘制一个元素(文本、图形)时,必须先指定它的颜色、文本字体再进行绘制,否则不会生效。
场景:假设你有一个游戏,UI在顶部,游戏动作在中间,静态背景在底部。
方法:游戏可分为三种
好处:避免固定组件的重复渲染。
设备屏幕上的像素(逻辑像素)可以视为正常像素(css中设置的像素),你可以正常使用。如果你画的是100px的东西,那也是100px的东西。但是在一些高分辨率屏幕的手机出现之后,一个属性devicePixelRatio就一起出现了。它允许我们查询设备像素比率。这里需要抛出一个名词逻辑像素,即当css设置为100px时,在iPhone 6/7 iPhone 6/7/8(devicepixelrratio为3)上,实际渲染为300px物理像素。比例为3: 1。
但是对我们开发者有什么影响呢?早些时候,我们注意到当我们在这个高分辨率屏幕上添加img时,我们的图形在devicePixelRatio的影响下变得非常模糊。
如何解决这个问题?如果我将img的宽度和高度分别乘以DevicePixelLatio,那么得到的大小会被绘制到屏幕中,DevicePixelLatio的大小会对齐缩放。Img将以高清的方式呈现。
但是,这种方法有一个问题,由于画布和内容是逐年放大的,然后进行缩放,所以绘制的图片大小会相应增加。建议根据要求判断是否需要HD操作。
画布动画的本质是不断的擦除和重绘,然后结合一些时间控制的方法来达到动画的目的。
显示器的刷新频率为60Hz,最流畅动画的最佳周期间隔为1000ms/60,约等于16.6ms。
requestAnimationFrame基于显示器的刷新频率,是浏览器专门为动画提供的API。运行时,浏览器会自动优化方法的调用,节省系统资源,提高系统性能。如果页面不活动,requestAnimationFrame()的调用将被挂起,以提高性能和电池寿命。
执行一个动画,让浏览器调用指定的回调函数,在下一次重绘前更新动画。这个方法需要传入一个回调函数作为参数,并返回一个requestID,这个函数将在浏览器下次重绘之前执行。
通过调用窗口取消先前添加到计划中的动画帧请求。cancelAnimationFrame()方法,并接受requestID。
浏览器兼容性
画布的每条线都有一条无限细的中心线,线条从中心线延伸。
解题的起点应该是0.5,这也是x和y需要+0.5的原因。当计算后x和y不一定是整数时,+0.5可能会再次出现模糊。所以四舍五入可以保证不会有歧义。
因为我们有能力“在画布上画出一幅画的一部分”。
在普通的html中,我们会将多个对象放在一张图片中,以减少请求的数量。这通常被称为“向导图”。但是,实际上存在一些潜在的性能问题。使用drawImage绘制一个大小相同的区域,数据源是一张与绘制区域大小相近的图片,与数据源是一张更大的图片(我们只是扣除数据)的情况相比,前者的成本更少。可以认为,两者之间的差额成本就是“切割”操作的成本。
虽然看起来成本差别不多,但是drawImage是最常用的API之一,我觉得有必要对其进行优化。优化的思路是提前做好“裁剪”这一步并保存,每一帧只画不裁剪。
我们可以先把要画的区域剪下来保存,这样每次画的时候都会轻松很多。
drawImage方法的第一个参数不仅可以接收一个图像对象,还可以接收另一个画布对象。而且用Canvas对象画图的成本和用Image对象差不多。我们只需要在画布上画出对象,而不需要插入页面,然后用这个画布画出每一帧。