【问题标题】:Scaling a canvas nicely with css使用 css 很好地缩放画布
【发布时间】:2015-04-04 06:15:55
【问题描述】:

我正在尝试在画布上绘制图像,然后使用 css 使画布适合特定大小。事实证明,许多浏览器并不能很好地缩小画布。 OS X 上的 Firefox 似乎是最差的之一,但我没有测试过很多。这是该问题的一个最小示例:

HTML

<img>
<canvas></canvas>

CSS

img, canvas {
  width: 125px;
}

JS

var image = document.getElementsByTagName('img')[0],
    canvas = document.getElementsByTagName('canvas')[0];

image.onload = function() {
  canvas.width = image.width;
  canvas.height = image.height;

  var context = canvas.getContext('2d');
  context.drawImage(image, 0, 0, canvas.width, canvas.height);
}

image.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Helvetica_Neue_typeface_weights.svg/783px-Helvetica_Neue_typeface_weights.svg.png"

在代码笔中运行:http://codepen.io/ford/pen/GgMzJd

这是 Firefox 中的结果(Retina 显示屏的屏幕截图):

发生的情况是&lt;img&gt;&lt;canvas&gt; 都以相同的大小开始,并由浏览器使用 css 缩小(图像宽度为 783px)。显然,浏览器在&lt;img&gt; 上做了一些很好的平滑/插值,但在&lt;canvas&gt; 上没有。

我试过了:

如何使右侧的图像看起来像左侧的图像?最好用尽可能少的代码(例如,我不想自己实现双三次插值)。

【问题讨论】:

  • 浏览器对 HTML 5 Canvas 有一个非常简单的下采样,see this answer here
  • 这个答案是我试图避免的一个完美例子:一个极其复杂的黑客攻击(看起来像)严重的性能影响。
  • 也许使用媒体查询来提供更接近显示尺寸的图像,因此调整大小不会那么明显?

标签: css html canvas


【解决方案1】:

画布并不完全意味着要进行 css 缩放:尝试过度采样:使用所需画布大小的两倍,并且 css 缩放可以很好地缩小画布。
在高 dpi 设备上,您应该再次将分辨率加倍以达到 相同的质量。

(即使在标准显示器上,X4 也会更亮一些)。

(图像、画布 1X、2X 和 4X)


var $ = document.getElementById.bind(document);
var image = $('fntimg');

image.onload = function() {
  drawAllImages();
}

image.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Helvetica_Neue_typeface_weights.svg/783px-Helvetica_Neue_typeface_weights.svg.png"

function drawAllImages() {
  drawImage(1);
  drawImage(2);
  drawImage(4);
}

function drawImage(x) {
  console.log('cv' + x + 'X');
  var canvas = $('cv' + x + 'X');
  canvas.width = x * image.width;
  canvas.height = x * image.height;
  var context = canvas.getContext('2d');
  context.drawImage(image, 0, 0, canvas.width, canvas.height);
}
img,
canvas {
  width: 125px;
}
<br>
<img id='fntimg'>
<canvas  id='cv1X'></canvas>
<canvas  id='cv2X'></canvas>
<canvas  id='cv4X'></canvas>
<br>

【讨论】:

  • 好的,过采样后看起来会好一些。但考虑价格。您以 2X 或 4X 画布的价格购买了更好的图像。最昂贵的 4X 价格可能是在最负担不起的移动设备上支付的。恕我直言,这里的过采样是一个糟糕的购买,最好创建几个通过媒体查询适当交付的预尺寸图像。
  • @markE :我同意,在适当的软件中手动缩小尺寸既可以提供更好的结果,也可以减少电池压力。加载图像后,也可以使用正确的代码缩小图像。但是,如果我们听从 O.P. 的要求:“尽可能少的代码”,我只能看到这个解决方案。
【解决方案2】:

您可以通过按window.devicePixelRatio 值缩放画布的后备存储来解决像素化问题。不幸的是,伪劣的图像过滤目前似乎是浏览器的限制,唯一可靠的解决方法是roll your own

将您当前的 onload 替换为:

image.onload = function() {
  var dpr = window.devicePixelRatio;
  canvas.width = image.width * dpr;
  canvas.height = image.height * dpr;

  var context = canvas.getContext('2d');
  context.drawImage(image, 0, 0, canvas.width, canvas.height);
}

结果:

在 Windows 8.1 上的 Firefox 35.0.1 上测试。请注意,您当前的代码不处理浏览器缩放事件,这可能会重新引入像素化。您可以通过处理调整大小事件来解决此问题。

【讨论】:

    【解决方案3】:

    缩放画布并认为您解决了图像缩放问题并不是一个好主意。您可以将动态值传递给画布,然后以您想要的任何大小绘制。 这是画布文档的链接:http://www.w3docs.com/learn-javascript/canvas.html

    【讨论】:

      【解决方案4】:

      简单的答案,你做不到。画布就像一个位图,仅此而已。

      我的想法: 您应该在缩放时重新绘制整个表面,并确保将您正在绘制的图像缩放到画布上。因为它是矢量图形,所以应该可以。但是您肯定必须重新绘制画布。

      【讨论】:

        猜你喜欢
        • 2020-01-16
        • 2014-01-04
        • 2015-02-27
        • 2013-09-20
        • 1970-01-01
        • 2010-12-30
        • 1970-01-01
        • 2011-10-10
        • 2016-09-26
        相关资源
        最近更新 更多