用css很好地缩放画布

for*_*ord 10 css html5 canvas

我正在尝试在画布上绘制图像,然后使用css将画布调整到一定的大小.事实证明,许多浏览器都没有很好地缩放画布.OS X上的Firefox似乎是最差的之一,但我没有测试过很多.以下是问题的最小示例:

HTML

<img>
<canvas></canvas>
Run Code Online (Sandbox Code Playgroud)

CSS

img, canvas {
  width: 125px;
}
Run Code Online (Sandbox Code Playgroud)

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"
Run Code Online (Sandbox Code Playgroud)

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

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

canvas_scaling_firefox.png

发生了什么事是,无论是<img><canvas>开始在相同的尺寸和用CSS被缩小浏览器(图像宽度为783px).显然,浏览器会对其进行一些很好的平滑/插值<img>,但不会<canvas>.

我试过了:

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

mm2*_*201 5

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

将当前的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);
}
Run Code Online (Sandbox Code Playgroud)

结果:

结果

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


Gam*_*ist 4

Canvas 并不完全意味着 css 缩放:尝试过度采样:使用所需画布大小的两倍,并且 css 缩放将在缩小画布方面做得很好。
在高 dpi 设备上,您应该将分辨率再提高一倍才能达到相同的质量。

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

图像、画布 1X、2X 和 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);
}
Run Code Online (Sandbox Code Playgroud)
img,
canvas {
  width: 125px;
}
Run Code Online (Sandbox Code Playgroud)
<br>
<img id='fntimg'>
<canvas  id='cv1X'></canvas>
<canvas  id='cv2X'></canvas>
<canvas  id='cv4X'></canvas>
<br>
Run Code Online (Sandbox Code Playgroud)