用css很好地缩放画布

时间:2015-02-04 16:19:09

标签: css html5 canvas

我试图在画布上绘制图像,然后使用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"

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

这是Firefox中的结果(来自视网膜显示屏的截图):

canvas_scaling_firefox.png

发生的事情是<img><canvas>都以相同的大小开始,并由浏览器按css缩小(图片宽度为783px)。显然,浏览器在<img>上进行了一些很好的平滑/插值,但在<canvas>上却没有。

我试过了:

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

4 个答案:

答案 0 :(得分:4)

您可以通过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);
}

结果:

Results

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

答案 1 :(得分:2)

Canvas并不意味着要进行css缩放:尝试过度采样:使用两倍所需的画布大小,css缩放在缩小画布时可以做得很好。
在hi-dpi设备上你应该再次加倍分辨率到达 相同的质量。

(即使在标准显示器上,X4也会闪耀一点)。

Image, canvas 1X, 2X and 4X (图片,画布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>

答案 2 :(得分:0)

缩放画布并认为您解决了图像缩放问题并不是一个好主意。您可以将动态值传递给画布,然后根据需要绘制该尺寸。 这是canvas doc:http://www.w3docs.com/learn-javascript/canvas.html

的链接

答案 3 :(得分:0)

简单回答,你不能这样做。画布就像一个位图,仅此而已。

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