欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
在这里,我们要郑重提醒一些已经学习了Canvas的读者,在设计应用的时候做足相关的技术理论准备工作,在一些基本的问题上花费一些时间,可以避免重大缺陷,并能创造更加令人惊艳的效果。
 
大家想一下两个问题:Canvas是不是透明的?Canvas可不可以互相堆叠在一起?下面我们给出上述两个问题的答案。
 
 Canvas是没有背景色的,也就是说Canvas默认是完全透明的,就像一块玻璃,而不是一块画布,如果非要理解成画布,那也应该是一块透明的“塑料画布”。
 Canvas在浏览器中纳入了DOM体系,是可以通过CSS 的Position和z-index值来操作任意多个Canvas堆叠在一起,合成效果就像操作div标签一样。
 
于是,得出的结论是:当一个Canvas有过多的绘图任务时,效率会越来越低下。根据上面两个答案,我们可以提出一个解决方案:我们可以利用Canvas的透明属性和可以堆叠的特征,剥离相关资源和绘图任务,使作品的结构更加清晰,更加适合团队开发。
 
避开浮点运算
当你的作品中有大量的浮点运算时,效率必然会下降很多。我们的建议是:对要计算的值先取整后再绘图,可以提高效率。这个小技巧在开发手机游戏或者需要大量渲染而对图形质量的要求可以降低的情况下,是非常有用的。
 
资源载入与双缓冲问题
在网上常见的Canvas开发教程中,有些代码看上去没有问题,但是实际上却不能在工程中直接使用,这样的代码只有教育意义。例如:
var ctx = mycanvas.getContext('2d');
var img = new image();
img.src="1.png";
ctx.drawImage(img);
在开发Canvas游戏时,常常会有很多资源需要载入,而且反复使用drawImage()方法时,如果没有做好资源载入控制,将带来非常严重的显示问题(有时候显示,有时候不显示,在动画情况下会闪烁)。因此,我们建议在开发中使用数组或JSON等对所有的游戏资源进行序列化,然后将相关资源一次性建立的相关对象存储在内存中,以便在下载完毕后,频繁读取时不必再去读图片资源,而是直接读内存中的资源。这样一来,一是速度快了许多,二是稳定性有了保障。
 
通常情况下,我们把上面所说的这种方法称为双缓冲绘图,也是游戏开发中最常见的方法。
 
下面给出一段图片资源预载双缓冲示例代码:
var game = {}; //游戏对象
var buffer=null; //预留缓冲区要在内存中开辟的对象
game.imgResource = [
{id: 'a1', src: 'image/1.jpg'},
{id: 'a2', src: 'image/2.png'},
{id: 'a3', src: 'image/3.png'}
]; //游戏对象中的图片资源对象序列化
var source={}; //资源对象
source.imgs = {}; //建立图片对象
for(var i =0;i<game.imgResource.length;i++){ //开始资源预载
source.loadImg(game.imgResource[i].id, game.imgResource[i].src);
}
source.loadImg = function(id, src){ //全部存入对象中
source.imgs[id] = new Image(); //开始存入对象中
source.imgs[id].src = src; //指定资源路径
source.imags[id].update(…) //将资源写入内存,此处省略
};
ctx.drawImage(buffer, 0, 0); //从内存缓冲区中读取资源
当图片全部载入内存后,就可以从内存中读取相关的资源进行绘图操作了,这时就不会再出现图片闪烁、忽隐忽现等问题了。这是Canvas新手需要注意的问题。
 
 
图片抗锯齿的原理及办法
图片的抗锯齿处理可能是很多人都关心的内容,某些有经验的开发人员也在实际开发和项目中遇到了这些问题而苦于没有解决办法。本节将对部分浏览器中Canvas里绘入图片后旋转产生锯齿的现象(此问题在非Safari的移动设备上尤其突出)进行解释、处理和优化,达到抗锯齿后的完美效果。
 
1. 概念简介
在介绍抗锯齿前,我们需要读者大概了解下面几个概念。
 位图(又叫:点阵图、栅格图、像素图)。简要来讲,位图就是以密集的点组成的图。从图形学的角度说,图像是光的复杂显示,我们可以把一幅图像的每个点都看成是一个光的格子,通常称为光栅,所以又有光栅图片一说。
 矢量图(又叫:向量图)。简要来讲,就是以各种复杂信息描述而成的图,记录的是点、线、面、颜色等信息。这样的图放大、缩小都不会造成锯齿,也不会失真,是最适合做电子地图、标识等显示的方案。
 锯齿。锯齿就是位图在某些角度上显示的时候,图片边缘出现毛边,类似锯齿一般,放大后仔细观察,就像是一个一个小格子,如下图所示。
 抗锯齿。抗锯齿就是让锯齿消失,在各种角度下,位图都平滑显示。
 
 
 
2. 锯齿问题的产生
关于抗锯齿,有些读者可能已经查阅了大量的资料,研究了大量的算法,但估计收获甚微。在这里,我们给出一个旋转的抗锯齿案例,简单且易操作,希望能抛砖引玉。
我们在一个工程案例中需要动态旋转一个圆形图片,想当然地以为可以非常简单地实现,结果在测试中发现锯齿很严重。除了在移动设备(比如iPhone、iTouch和iPad)上使用Safari看起来比较平滑能够接受之外,在其他任何浏览器上测试时都有锯齿。
 
3. 锯齿问题的分析
在计算机图像处理中,一幅位图的平面角度动态变化(旋转)显示是比较有意思的。设画布的尺寸为400×400像素,圆在画布的正中,半径为100像素,当一个圆形图片在旋转时,实际上是一个以圆直径为边长的正方形在旋转。我们先看一下正方形在未旋转前各坐标点的分析,其中标出了圆心O和A、B、C、D、E、F、G、H几个点的坐标,如上图所示。
图片在旋转后,图中的所有点都发生了变化,特别是圆心点,处于上下左右的小数位移状态,如下图所示。
 
 
 
经过这次旋转计算,原图像点和采样后重新渲染的点都不能互相对应上,造成有的点溢出到不应该显示的地方,而有的点由于位置不对不再显示。而在使用软件渲染器旋转图片的时候,就算是双线性插值也不能完全保证(特别是有弧线的)能够一一对应。这就是锯齿产生的原因。
 
4. 锯齿问题的解决办法
既然找到了原因,就可以想出解决办法。一般来说解决办法至少有4种:
(1) 使用硬件渲染(以苹果公司移动设备中的Safari为代表)。
(2) 使用矢量图(如果可以替代的话)。
(3) 图像以2的幂或倍数放大,尽可能保证渲染器采样到原图而不是插值。
(4) 以复杂的抗锯齿算法来解决这个问题(但这种方法计算量大,而且非专业人员看不懂,更别提使用了)。
 
看到这里,我想大家已经明白了,我们要采用的是第三种办法。
假设要在设备中显示一幅200×200的图,并旋转,则使原图增大一倍,达到400×400,这样做的目的确保源图采样质量,然后再将此图多设1个像素,相当于手动添加中心围绕点(最关键的一步),为什么要添加1个像素的中心围绕点呢?这是为了方便渲染器计算。一幅400×400的图,如果旋转起来,半径是多少?很多人认为是200,其实不是200,而是约等于199.5,因为图形在旋转中需要有一个圆心。因此,我们给此图再手动加一个空白像素,使旋转的半径为整数200。增加了中心旋转点后,一方面提升了计算效率,另一方面使渲染器的每个点都能够比较准确地落在原点上。因此,源图的尺寸达到401×401,至此,锯齿问题能够得到圆满的解决。
本文是抗锯齿中一个较为粗暴有效的办法,一般在计算机图形处理中与抗锯齿相关的有“双线性插值、临近采样、双三卷积”等重采样方法,有兴趣深入了解的读者,可以按照这几个关键词去查找资料进行了解。
 
 
粒子系统的使用
什么是粒子系统?很难直接描述,但是大家都看到过火焰,火焰的状态是没有固定形状的,在空气中,火焰翻腾跳跃。如何用HTML5的Canvas去描绘火焰呢?有两种方法。一种方法是用多幅图片,帧式快速播放,给人一种火焰在跳动的感觉。但是这样生成的效果非常简单,火焰的形态也很枯躁。另一种方法就是这里要介绍的粒子系统,完全依赖计算和编程,模拟出火焰的形态,给人强烈的真实感受。
 
粒子系统原来是计算机三维图形学中的技术,像火焰、爆炸、流水、云等,都可以模拟得非常真实。在实际工作中,限于移动设备的环境,我们不能进行大量的计算,因此,建议读者在实际开发中,做好衡量和取舍,采取适当的粒子数量,以便既保证效果又能让程序高效地运行。
 
有一点是可以确定的:采用了适应粒子系统效果的游戏和应用,可以节省大量的图片资源,载入时间短,帧数高,速度快。
 
因此,我们建议用大量图片去堆出效果的游戏和应用采用粒子系统,事半功倍。
 

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h61249.shtml