HTML5画布 - 相对于对象中心进行缩放而不移动上下文。

5

我正在开发一个canvas游戏,其中有多个粒子生成器。这些粒子在创建后逐渐缩小。为了从它们的中心点缩小粒子,我使用了context.translate()方法:

context.save();
context.translate(particle.x, particle.y);
context.translate(-particle.width/2, -particle.height/2);
context.drawImage(particle.image, 0, 0, particle.width, particle.height);
context.restore();

我读过几篇文章,声称save(),translate()和restore()方法计算成本相当高。是否有其他替代方法可以使用?

我的游戏针对移动浏览器,因此我正在尽可能地优化性能。

提前感谢!

1个回答

9

是的,只需在最后使用setTransform()而不是使用save/restore:

//context.save();
context.translate(particle.x, particle.y);
context.translate(-particle.width/2, -particle.height/2);
context.drawImage(particle.image, 0, 0, particle.width, particle.height);
//context.restore();
context.setTransform(1,0,0,1,0,0);   // reset matrix

假设没有其他累积变换在使用(在这种情况下,您可以重构代码以在需要时设置绝对变换)。作为参数给定的数字是表示身份矩阵的数字,即重置矩阵状态。这比保存/恢复方法要快得多,后者不仅存储和恢复变换状态,还存储风格设置、阴影设置、剪辑区域等等。您也可以将两个平移调用合并为单个调用,并使用乘法代替除法(CPU级别上更快):
context.translate(particle.x-particle.width*0.5, particle.y-particle.height*0.5);

或者直接使用x/y坐标与粒子"着色器"一起使用,而无需进行任何翻译。


1
谢谢 - 这个小改变增加了移动性能10-20fps。非常感谢! - Peter Ringelmann
2
通过一个好的答案显著地改善提问者的代码可以得到点赞。我可能还要补充一点,如果仅需要翻译,则可以避免使用 context.translate 并直接更改 x、y 坐标。 - markE
我最初避免使用它,因为我不知道完整的情况,但现在已经包括进来了,这样选项更清晰(这是我个人更喜欢的选项 - 我正在我的粒子引擎中使用它)。谢谢markE。还添加了更多细节。 - user1693593
谢谢更新 - 我现在只使用x和y坐标:context.drawImage(particle.image, particle.x-particle.width/2, particle.y-particle.height/2, particle.width, particle.height); 但是现在旋转不起作用了。可以安全地假设这种方法只适用于缩放/平移吗? - Peter Ringelmann
@PeterRingelmann 如果你在其中有一个旋转,你需要将它们分开(将其转换为原点,旋转,然后使用图像的高度和宽度将其转换回来)。在这种情况下,你做得很正确(旋转调用不在原始代码片段中,这就是我建议压缩它的原因)。 - user1693593
1
@KenFyrstenberg 是的,我可能应该包含它...尽管我想让我的代码片段尽可能简洁。我在stackoverflow上还是相当新手 :) 再次感谢您的建议 - Peter Ringelmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接