浏览 4311 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-02-11
========================= 随着iphone4 的推出, retina(视网膜)屏在移动设备中被越来越广泛的应用. 不过,虽然retina屏给画面的展现带来了前所未有的清晰平滑的效果,却给开发人员带来了一些小小的麻烦. 网上针对如何在 retina屏下设计软件的UI 有很多文章,在这里我不想重复这些内容, 而是想针对HTML5 canvas在retina屏上的应用说一说我的一点心得. 最近业余时间一直在利用HTML5技术开发游戏引擎. 一切进行的还算顺利, 但是当我在 iphone4上测试该引擎时, 发现其性能比在 itouch3上还要低,而且低很多. 造成这一现象的主要原因就是 retina屏. 下面先简单说说 retina屏设备如何处理 canvas的. (本文以iphone4 为例). ip4的safari浏览器在展现canvas上的图像时, 为了得到和传统屏幕一样的视觉大小, 会将原始像素放大1倍.(retina屏幕的像素更小,可以理解为4个retina像素表示1个传统像素). ip4在进行这种放大时,并不是简单的 将1*1像素 变成2*2像素, 而是会进行"复杂的放大算法", 目的是得到更加平滑自然(类似抗锯齿)的图像. 虽然这种放大操作是native的,但还是会导致渲染canvas时性能变得极其低下(可能还有其他原因). ========================================== 据我所知,目前在ip4的safari里,我们无法人为的控制这种放大操作(禁止放大,或者简化放大算法). 不过我们还是有一些技巧来对canvas进行一些优化, 从而提高它在retina屏幕上的性能. 假设我们要在ip 3GS上做如下操作: 1 加载一个 50*50 的图片. 2 创建一个 300*300 的 canvas. 3 将这个图片 绘制在 canvas的 ( 100 , 100 )坐标处. (以上单位均为:像素) 那么在iphone4上,我们不做任何修改执行同样的代码, 会得到视觉效果几乎一样的结果. 但是实现的性能会很低.如果是做游戏或是动画,这个性能差距往往是我们难以接受的. 下面看一看在ip4下如何优化这一个操作: 1 加载一个 50*50 的图片. 2 将此图片放大1倍,变为 100*100 , 放大操作通过代码来实现,可采用"简单的1变4算法". (以上两步也可以变为直接加载一个 已经制作好的 100*100的 大图片) 3 创建一个 600*600 的 canvas ( 即,原始的宽高都乘以 2 ) 4 设置该canvas的 style.width=300 和style.height=300 (也就是说,style的大小仍为原始大小) (注意: canvas的style.width/height 有别于div的,意义完全不同,具体的请自行google) 5 将放大的图片 绘制在 canvas的 ( 200 , 200 )坐标处.(即,原始的横纵坐标都乘以 2 ) 通过这个方案实现的效果和 优化之前以及在ip3GS上的效果 几乎完全一样(肉眼难以察觉), 但是性能却比 优化前 提高近50%. 优化方案中的第4步最为关键, 也是性能之所以优化的关键所在. 其他几步的核心就是 "在2倍大的canvas上绘制2倍大的图片", 按理说应该性能更低才对. 但是由于 canvas的style大小只是 canvas的实际大小的一半, 一切就变得不同了. 当执行以下代码: canvas.width=600; canvas.height=600; canvas.style.width="300px"; canvas.style.height="300px"; canvas的实际大小变为了300*300, 同时, canvas的坐标系发生了缩放,缩放比为 300/600; 也就是说 canvas上所有的点的大小和坐标都缩小了一半, 所以之前 "在2倍大的canvas上绘制2倍大的图片",缩小一半后(这个缩小的算法也是一个复杂的缩小算法). 先放大再缩小,于是最后相当于什么都没有变. 到这里也许有人会迷糊: 先放大,再缩小, 然后绘制在ip4的retina屏上.为什么比"直接绘制"性能高?按道理多了一步操作,应该更慢才对. 其实我也迷糊. 不过当我们了解了以上每一步的操作后, 不妨可以这样理解(纯属我个人不负责的猜想): 优化前: 50*50像素 通过"复杂的放大算法"转变为 100*100 像素 优化后: 50*50像素 通过"简单的放大算法"变为100*100 像素, 100*100 像素 通过 "复杂的缩小算法"变为50*50 像素, 50*50像素 通过"复杂的放大算法"转变为 100*100 像素 "复杂的缩小算法" 和 "复杂的放大算法" 两者在ip4内部很可能是互为逆操作,于是相互抵消了.所以优化后就是: 50*50像素 通过"简单的放大算法"转变为 100*100 像素. 实际上也许不是根本这么回事,但是姑且这么理解吧, 我实在找不出更合理的解释了,我更没能力去研究ip4和IOS4底层的实现机制. (如果你知道真实的原因一定要告诉我啊 谢谢了 ) 下面是一个我写的一个更复杂的示例: http://data.wiyun.com/finscn/retina/test-retina.html 有iphone4 或者是 itouch4 的朋友可以访问一下试一试, 看看选择优化前和优化后的FPS变化. 注1: 在非retina屏幕上测试没有效果; 注2: 该网页内容极其简单,绝对不会耗费多少您的网络流量,不过该服务器带宽和磁盘IO有限,所以打开速度可能很慢 目前根据网友的反馈: 优化前FPS为 32FPS左右, 优化后为 45左右. 最后再强调一下 : 本文提到的优化方案是正确的(至少在iphone4 和itouch4, iOS4.1 上是正确的),但是原理纯粹是我胡乱分析的(根据结果猜原因). 望知道真实原因的朋友指正. 谢谢了 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-02-21
没给iphone开发过,但是lz,
我觉得“ip4的safari浏览器在展现canvas上的图像时, 为了得到和传统屏幕一样的视觉大小, 会将原始像素放大1倍.(retina屏幕的像素更小,可以理解为4个retina像素表示1个传统像素). ”这个不太可能吧。。。 你300*300的图像他给你放大了两倍,那你960*640的图像呢?也给你放大两倍?他依据什么给你放大的。再者说,如果retina做这种操作,不是等于把自己高分辨率的优势给废了吗? |
|
返回顶楼 | |
发表时间:2011-02-21
safari浏览器 就是这样的.
换句话说 IP4下, 只有本地应用才能充分发挥retian的优势. 浏览器应用比较麻烦 例如 显示 100*100的图片 , 为了得到好的效果, 你需要准备200*200的大图, 然后 <img width="100" height="100" src="大图"/> |
|
返回顶楼 | |
发表时间:2011-02-23
fins 写道 safari浏览器 就是这样的.
换句话说 IP4下, 只有本地应用才能充分发挥retian的优势. 浏览器应用比较麻烦 例如 显示 100*100的图片 , 为了得到好的效果, 你需要准备200*200的大图, 然后 <img width="100" height="100" src="大图"/> 如果canvas 为960*640分辨率呢?还放大吗? |
|
返回顶楼 | |
发表时间:2011-02-23
放大.
因为 ip4的浏览器已经规定了 页面元素定义的像素 和 物理像素之间的 比例是 2 这个属性现阶段无法修改 (或者是我不知道怎么修改.... 有知道的吗? ) |
|
返回顶楼 | |
发表时间:2011-03-04
http://stackoverflow.com/questions/3707509/startup-image-in-webapp-for-retina-display
有人讨论这个问题 看来iphone4 的分辨率 就是bug一样的存在啊 |
|
返回顶楼 | |