我想知道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.width
和style.height
中。因此,如果您使用的是标准模式,请确保将其设置为"200px"
而不是200
,否则画布将无法缩放。
答案 0 :(得分:1)
为获得最佳结果,应使画布尺寸与其分辨率相同。如果画布上没有任何透明像素,则应关闭Alpha。
使用const ctx = canvas.getContext("2d",{alpha: false})
对于大多数设备而言,缩放并不比绘制未缩放图像昂贵。
渲染成本下降到绘制的像素数,而不是源中的像素数。
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