CSS缩放比drawImage缩放更有效吗?

时间:2019-09-23 12:54:16

标签: javascript html5-canvas scaling css-transforms drawimage

我想知道drawImage和CSS缩放之间的区别是什么。我同时尝试了两者,而CSS似乎给出了稍微更平滑的结果,而drawImage往往会有些失真-尤其是当我平移图像时,在多个动画帧的过程中,从不同的源x和y发出斑点。在以许多不同的比例因子进行测试之后,我得出了这个结论。我在下面有一个简单的例子。

var img = new Image();
var ctx = document.querySelector("canvas").getContext("2d");

img.src = "img1000x1000.png";// width and height are 1000

ctx.canvas.width  = 100;
ctx.canvas.height = 100;
ctx.imageSmoothingEnabled = false;

这将在img完全加载后运行。

// method 1 uses drawImage to scale
ctx.drawImage(img, 0, 0, 100, 100, 0, 0, 200, 200);

// method 2 draws the img with no scaling and then uses css to scale
ctx.drawImage(img, 0, 0, 100, 100, 0, 0, 100, 100);
ctx.canvas.style.width  = 200;
ctx.canvas.style.height = 200;

请紧记,我并不总是将尺寸缩放到正好2倍,而是从img的不同区域中抽签。我只将整数上交到drawImage,以使内容尽可能清晰。我还拥有image-rendering:pixelated以及CSS画布上定义的其他变体,用于CSS缩放以使情况保持清晰。

对于我的具体示例,我知道我可以将img放大一次,然后平移到最终缩放的img,但这不是问题。问题是哪个表现更好。对于我的应用程序,我必须在每个帧上按比例放大一个动画图块地图,因此我要从多个源向1:1空间中的画布进行缩放,然后使用requestAnimationFrame将最终的画布每秒缩放30至60次。

最后,他们给出了非常相似的结果。 CSS仅比原始图像更清晰明了。 CSS更快/更有效吗?还是用drawImage缩放更有效?

注意/编辑:

我发现,如果我在<!DOCTYPE html>中使用标准模式,则必须将字符串值传递给CSS方法的style.widthstyle.height中。因此,如果您使用的是标准模式,请确保将其设置为"200px"而不是200,否则画布将无法缩放。

1 个答案:

答案 0 :(得分:1)

画布Alpha有所作为

为获得最佳结果,应使画布尺寸与其分辨率相同。如果画布上没有任何透明像素,则应关闭Alpha。

使用const ctx = canvas.getContext("2d",{alpha: false})

关闭画布Alpha

缩放无关紧要

对于大多数设备而言,缩放并不比绘制未缩放图像昂贵。

渲染成本下降到绘制的像素数,而不是源中的像素数。

估算渲染成本

drawImage的费用

如果画布分辨率为200 x 200,并且您绘制的图像ctx.drawImage充满了需要渲染的40,000像素。

合成成本

如果通过CSS规则缩放画布,即使alpha处于禁用状态,也必须将canvas元素合成才能显示。费用将是画布大小占用的像素数。

如果画布的alpha为true,则必须将其与背景合成,因此渲染成本为画布的显示尺寸(以像素为单位)。

如果画布大小(CSS)与分辨率匹配,并且alpha处于关闭状态,则不需要为最终呈现而将画布进行合成,并且没有额外的合成成本。

渲染成本示例

  • canvas是可见的画布元素
  • image是可以放入GPU RAM的图像

最好关闭alpha且不缩放CSS

canvas.width = canvas.height = 100;
canvas.style.width = canvas.style.height = "100px";
const ctx = canvas.getContext("2d", {alpha: false});
ctx.drawImage(image, 100, 100);

// Total rendering cost 100 * 100 = 10,000 pixels

通过CSS缩放并关闭alpha

canvas.width = canvas.height = 200;
canvas.style.width = canvas.style.height = "100px";
const ctx = canvas.getContext("2d", {alpha: false});
ctx.drawImage(image, 200, 200);

// Total rendering cost 200 * 200 + 100 * 100 = 50,000 pixels

启用alpha渲染,无需CSS缩放

canvas.width = canvas.height = 100;
canvas.style.width = canvas.style.height = "100px";
const ctx = canvas.getContext("2d");  // alpha is on
// same as const ctx = canvas.getContext("2d", {alpha: true});
ctx.drawImage(image, 100, 100);

// Total rendering cost 100 * 100 + 100 * 100 = 20,000 pixels

注释

  • 由于页面设置,滚动和各种其他因素,不可避免的渲染成本。由于无法避免,因此忽略了这些费用。
  • 可能无法在所有浏览器上使用开启字母转换选项。
  • 软件渲染和设备功能将对渲染性能产生最大的影响。
相关问题