我想知道用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
,否则您的画布将无法缩放。
为了获得最佳结果,应使画布尺寸与其分辨率相同。如果画布上没有任何透明像素,则应关闭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
注释