【发布时间】:2016-12-09 04:24:37
【问题描述】:
我正在使用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) + ")";
});
#editor-container {
background-color: #001723;
}
#graph-container { transform-origin: top center; }
<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>
此图像是一个画布绘制的形状,它以交互方式可视化两个图形节点之间的连接,导出为 png。
请缩小,看看那条线有多嘈杂,即使缩放是以0.25 为步长并使用 CSS 完成的。 我怎样才能摆脱这种像素噪音? 这个问题发生在最新的 Google Chrome 和 Microsoft Edge 中,在其他浏览器中未经测试。无论是否使用 3D GPU 加速,都会出现此问题。
注意:显然,这是Minimal, Complete, and Verifiable example,实际工作要复杂得多。
数百个线条形状按程序绘制到画布上(每行toDataUrl(每行约40ms)异步缓存到
img元素,这样屏幕平移——这也是一个必需的功能——工作更顺畅,因为在屏幕上移动img元素比移动canvas元素(或在单个画布上重绘所有线条)便宜得多,无论是元素本身、容器还是被翻译成给定方向的浏览器视口。因此,生成 mipmap 并不是真正的选择,或者只能作为最后的手段,因为它会带来显着的性能损失(每个 mip 级别都会必须缓存到单独的图像上,至少将性能降低一半)。不过,我愿意相信这是可以避免的。在每个缩放步骤上重新绘制线条形状将无情地抹杀幻灯片的性能。
以下是我试过的东西列表,没有效果:
- 通过在形状元素本身或容器上定义以下 CSS 属性值来暗示更好的图像质量:
image-rendering: pixelated | optimizeSpeed | optimizeQuality
- 使用虚拟
transform强制将渲染层提升为 GPU 加速 - 使用
scale3d代替scale - 将
img.width和img.height减半,然后通过将img.style.width和img.style.height加倍进行补偿 - 不将画布结果缓存到
img,而是直接显示canvas元素(性能较慢,质量同样差)
我也尝试在缩小时使用filter: blur,但它是did not yield a better quality,因为在屏幕上呈现给定形状之后应用了模糊效果。
除了创建每个形状的下采样版本,有效地创建软件渲染的 mipmap (LOD) 系统之外,我还能做些什么来消除这种像素噪声?(正如我所写的那样,想强烈避免)
这个问题与similar questions 调查因缩小导致的不良图像质量有什么不同?
- 在这里,它是缩小尺寸的容器(并使用 CSS 转换),而不是单个图像元素。不对实际图像数据进行任何操作,这在类似主题中进行了讨论。
【问题讨论】:
-
我在 Chromium 中看不到任何像素噪点。版本 48.0.2564.82 Ubuntu 15.04(64 位)。
-
为什么您认为设置图像尺寸或使用变换会有所不同?这个问题确实和类似的问题没有什么不同。如果设置图像渲染属性没有帮助,您只能尝试使用更大的图像开始,例如。对于 200x200px 目标分辨率,使用 400x400px 图像,并且下采样结果在非整数比例下应该更平滑。
-
像素图像缩小的方式也因操作系统和浏览器而异。我在 MBP - Retina 和标准屏幕(Firefox 和 Safari)上进行了测试。我觉得没问题(尝试缩放):imgur.com/a/E2l2B
-
我个人认为 SVG 会是这里的出路。 可缩放矢量图形等等。例如,您提供的演示是一个简单的
path,其中一条贝塞尔曲线带有marker-end箭头。 -
@john-white 如果您以与渲染不同的尺寸显示图像,您已经在客户端进行下采样。
标签: javascript css canvas