【问题标题】:What is the most efficient way to tile an image using canvas?使用画布平铺图像的最有效方法是什么?
【发布时间】:2021-03-23 19:14:38
【问题描述】:

我最近一直在开发一个平台游戏,我想在其中添加一些图像。 我的目标是在使用尽可能少的 CPU/GPU 的同时平铺图像,我尝试了两种解决方案:使用drawImage() 绘制每个图像并使用createPattern 填充样式。

for循环方法:

ctx = canvas.getContext("2d");

for (let i=0; i<heightInTiles; i++) { 
  for (let j=0; j<widthInTiles; j++) {
    ctx.drawImage(image, screenX + j * blockSize, screenY + i * blockSize);
  }
}

此解决方案的问题在于,单独绘制每个图像会消耗大量 CPU 和 GPU。有没有办法让这更有效? (就像 50% 的 CPU 效率一样?)

fillStyle方法

var pat = ctx.createPattern(image, "repeat");
ctx.fillStyle = pat;
ctx.fillRect(screenX, screenY,   
             widthInBlocks * blockSize,
             heightInBlocks * blockSize);

这个解决方案不会占用太多空间,但它有一个奇怪的效果:图案只与画布的左上角对齐。

我只是在寻找一种更快的方法来将我需要的图块绘制到屏幕上。你们能帮我解决这个问题吗?

【问题讨论】:

    标签: javascript html canvas html5-canvas


    【解决方案1】:

    转换模式

    图案是迄今为止使用 2D API 重复图案的最快方法。为了获得更好的结果,您需要使用 WebGL。

    要移动模式,您需要通过DOMMatrix 使用pattern.setTransform( 来操作转换

    示例

    设置图案的起始位置

    var pat = ctx.createPattern(image, "repeat");
    pat.setTransform(new DOMMatrix([1,0,0,1,screenX, screenY])); // set top left starting 
                                                                 // pos of pattern
    ctx.fillStyle = pat;
    ctx.fillRect(screenX, screenY, widthInBlocks * blockSize, heightInBlocks * blockSize);
    

    【讨论】:

    • nitpick: DOMMatrix 需要new。虽然我知道您确实知道,但请注意,对于不支持 CanvasPattern.setTransform 的旧浏览器,您也可以设置上下文之一并在 fillRect 调用中对抗翻译,甚至分离路径声明并填充两个不同的矩阵变换。
    • @Kaiido SO上有很多遗留示例,例如stackoverflow.com/a/47838137/3877726
    猜你喜欢
    • 2017-10-11
    • 2019-09-03
    • 2011-06-17
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 2016-01-13
    • 1970-01-01
    相关资源
    最近更新 更多