提高CSS缩小尺寸元素的图像质量

Joh*_*isz 12 javascript css canvas

我正在使用的缩小图形编辑器的内容transform: scale(x).当缩小比例向下0(不包括)时,当放大比例上升时,最大为1(包括),这意味着完全缩放或初始比例.

但是,当缩小时,图像质量开始变得非常嘈杂 - 请考虑以下示例,并注意缩小将使图像外观嘈杂:

var graphContainer = document.getElementById("graph-container");
var zoomInButton = document.getElementById("zoom-in-button");
var zoomOutButton = document.getElementById("zoom-out-button");
var zoomLevel = 1;

zoomInButton.addEventListener("click", function () {
    zoomLevel = Math.max(1, zoomLevel - 0.25);
    graphContainer.style.transform = "scale(" + (1 / zoomLevel) + ")";
});

zoomOutButton.addEventListener("click", function () {
    zoomLevel = zoomLevel + 0.25;
    graphContainer.style.transform = "scale(" + (1 / zoomLevel) + ")";
});
Run Code Online (Sandbox Code Playgroud)
#editor-container {
    background-color: #001723;
}

#graph-container { transform-origin: top center; }
Run Code Online (Sandbox Code Playgroud)
<div id="editor-container">
    <button id="zoom-in-button">Zoom in</button>
    <button id="zoom-out-button">Zoom out</button>
    <div id="graph-container">
        <img class="shape" src="http://i.imgur.com/zsWkcGz.png" />
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

演示也在JSFiddle上

此图像是画布绘制的形状,以交互方式显示两个图形节点之间的连接,并导出到png中.


请缩小并查看该行的噪音,即使0.25使用CSS 进行缩放也是如此.如何摆脱这种像素噪音?问题出现在最新的Google Chrome和Microsoft Edge中,在其他浏览器中未经测试.无论有没有3D GPU加速,都会出现问题.

注意:显然,这是一个最小的,完整的,可验证的例子,真正的工作量是更复杂的.

线条形状的渐变在程序上绘制到画布上(每行<1ms),然后在空闲时img使用toDataUrl(每行约40ms)异步缓存到元素,因此屏幕平移 - 这也是必需的功能 - 工作更顺畅,因为img在屏幕上移动canvas元素比移动元素(或重绘单个画布上的所有线条)要便宜得多,无论是元素本身,容器还是转换为给定方向的浏览器视口.

因此,生成mipmap并不是一种选择,或者只是作为最后的手段,因为它会带来显着的性能损失(每个mip级别必须缓存到单独的图像上,至少将性能降低一半) ).不过,我想相信它是可以避免的.在每个缩放步骤上重绘线条形状将巧妙地消除性能直至幻灯片放映.

以下是我尝试过的事情清单,没有效果:

  • 通过在形状元素本身或容器上定义以下CSS属性值来提示更好的图像质量:
image-rendering: pixelated | optimizeSpeed | optimizeQuality
Run Code Online (Sandbox Code Playgroud)
  • 强制使用虚拟对象将渲染层提升为GPU加速 transform
  • 使用scale3d而不是scale
  • 减半img.width,img.height然后通过加倍img.style.width和补偿来补偿img.style.height
  • 不将画布结果缓存到img并直接显示canvas元素(性能较慢,质量相同)

我也尝试filter: blur在缩小时使用,但它没有产生更好的质量,因为模糊效果本身是在屏幕上呈现给定形状应用的.

除了创建每个形状的下采样版本之外,我还能做些什么来消除这种像素噪声,有效地创建了一个软件渲染的mipmap(LOD)系统?(就像我写的那样,我想强烈避免)


这个问题与从降尺度调查不良图像质量的一系列类似问题有什么不同?

  • 在这里,它是缩小(并使用CSS转换)而不是单个图像元素的容器.没有对实际图像数据进行操纵,这是在类似主题中讨论的内容.

Dav*_*mez 3

使用 SVG 图像而不是 PNG 可以获得更好的结果,它们也很容易生成并嵌入到您的代码中,您甚至不需要托管它们。

正如您在此演示中所看到的,SVG 不会像素化或变得模糊,并且您将在 Retina 等高分辨率屏幕上获得更好的结果。

SVG 代码:

<svg class="shape" width="440px" height="319px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <path d="M1,316.040132 C1,316.040132 241.5837,339.680482 241.5837,163.497447 C241.5837,-12.6855883 439,2.31775322 439,2.31775322" id="Path" stroke="#50E3C2" stroke-width="2"></path>
    </g>
</svg>
Run Code Online (Sandbox Code Playgroud)

显然并不完美。