CSS 缩放是否比 drawImage 缩放更有效?
Is CSS Scaling More Efficient than drawImage Scaling?
我想知道 drawImage
和 CSS 缩放之间的区别是什么。我都试过了, CSS 似乎给出了稍微平滑的结果,而 drawImage
往往有点失真 - 特别是如果我正在平移图像,在几个过程中从不同的源 x 和 y 发出 blitting动画帧。在对许多不同的比例因子进行测试后,我得出了这个结论。我在下面有一个简单的例子。
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 的不同区域进行 blitting。我只将整数交给 drawImage 以使事情尽可能清晰。我还有 image-rendering:pixelated
和 CSS 中 canvas 上定义的其他变体,用于 CSS 缩放以保持清晰。
我知道对于我的具体示例,我可以将 img 放大一次并在最终缩放的 img 周围平移,但这不是问题所在。问题是哪个性能更好。对于我的应用程序,我必须在每一帧上放大一个动画瓦片地图,所以我从多个来源 blitting 到 1:1 space 中的 canvas,然后放大最终的 canvas 使用 requestAnimationFrame 每秒 30 到 60 次。
最后,他们给出了非常相似的结果。 CSS 几乎没有更清晰和真实的原始图像。 CSS 更快/更有效率吗?还是使用 drawImage 缩放更高效?
注/编辑:
我发现如果我将标准模式与 <!DOCTYPE html>
一起使用,我必须将字符串值传递给 style.width
和 style.height
以用于 CSS 方法。因此,如果您使用的是标准模式,请确保将它们设置为 "200px"
而不是 200
否则您的 canvas 将无法缩放。
Canvas 阿尔法与众不同
为了获得最佳效果,您应该保持 canvas 大小与其分辨率相同。如果 canvas 没有任何透明像素,您应该关闭 alpha。
使用 const ctx = canvas.getContext("2d",{alpha: false})
关闭 canvas alpha
缩放无关紧要
对于大多数设备来说,缩放并不比绘制未缩放的图像更昂贵。
渲染成本取决于绘制的像素数,而不是源中的像素数。
估算渲染成本
drawImage
的成本
如果 canvas 分辨率为 200 x 200,并且您绘制了一个图像 ctx.drawImage
来填充需要渲染的 40,000 像素。
合成成本
如果 canvas 通过 CSS 规则缩放,即使 alpha 关闭,canvas 元素也必须合成才能显示。成本将是 canvas 大小占用的像素数。
如果 canvas 的 alpha 为真,则它必须与背景合成,因此渲染成本是 canvas 的显示尺寸(以像素为单位)。
如果 canvas 大小 (CSS) 与分辨率匹配并且 alpha 关闭,则 canvas 不需要为最终呈现进行合成,并且没有额外的合成成本。
渲染成本示例
canvas
是一个可见的 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
注释
- 由于页面设置、滚动和其他各种因素,渲染成本不可避免。这些成本无法避免,因此被忽略。
- 并非所有浏览器都提供关闭 alpha 的选项。
- 软件渲染和设备功能将对渲染性能产生最显着的影响。
我想知道 drawImage
和 CSS 缩放之间的区别是什么。我都试过了, CSS 似乎给出了稍微平滑的结果,而 drawImage
往往有点失真 - 特别是如果我正在平移图像,在几个过程中从不同的源 x 和 y 发出 blitting动画帧。在对许多不同的比例因子进行测试后,我得出了这个结论。我在下面有一个简单的例子。
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 的不同区域进行 blitting。我只将整数交给 drawImage 以使事情尽可能清晰。我还有 image-rendering:pixelated
和 CSS 中 canvas 上定义的其他变体,用于 CSS 缩放以保持清晰。
我知道对于我的具体示例,我可以将 img 放大一次并在最终缩放的 img 周围平移,但这不是问题所在。问题是哪个性能更好。对于我的应用程序,我必须在每一帧上放大一个动画瓦片地图,所以我从多个来源 blitting 到 1:1 space 中的 canvas,然后放大最终的 canvas 使用 requestAnimationFrame 每秒 30 到 60 次。
最后,他们给出了非常相似的结果。 CSS 几乎没有更清晰和真实的原始图像。 CSS 更快/更有效率吗?还是使用 drawImage 缩放更高效?
注/编辑:
我发现如果我将标准模式与 <!DOCTYPE html>
一起使用,我必须将字符串值传递给 style.width
和 style.height
以用于 CSS 方法。因此,如果您使用的是标准模式,请确保将它们设置为 "200px"
而不是 200
否则您的 canvas 将无法缩放。
Canvas 阿尔法与众不同
为了获得最佳效果,您应该保持 canvas 大小与其分辨率相同。如果 canvas 没有任何透明像素,您应该关闭 alpha。
使用 const ctx = canvas.getContext("2d",{alpha: false})
缩放无关紧要
对于大多数设备来说,缩放并不比绘制未缩放的图像更昂贵。
渲染成本取决于绘制的像素数,而不是源中的像素数。
估算渲染成本
drawImage
的成本
如果 canvas 分辨率为 200 x 200,并且您绘制了一个图像 ctx.drawImage
来填充需要渲染的 40,000 像素。
合成成本
如果 canvas 通过 CSS 规则缩放,即使 alpha 关闭,canvas 元素也必须合成才能显示。成本将是 canvas 大小占用的像素数。
如果 canvas 的 alpha 为真,则它必须与背景合成,因此渲染成本是 canvas 的显示尺寸(以像素为单位)。
如果 canvas 大小 (CSS) 与分辨率匹配并且 alpha 关闭,则 canvas 不需要为最终呈现进行合成,并且没有额外的合成成本。
渲染成本示例
canvas
是一个可见的 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
注释
- 由于页面设置、滚动和其他各种因素,渲染成本不可避免。这些成本无法避免,因此被忽略。
- 并非所有浏览器都提供关闭 alpha 的选项。
- 软件渲染和设备功能将对渲染性能产生最显着的影响。