我试图在画布上绘制图像,然后使用css将画布调整到一定的大小。事实证明,许多浏览器都不能非常好地缩放画布。 OS X上的Firefox似乎是最差的之一,但我还没有经过多少测试。以下是问题的最小示例:
<img>
<canvas></canvas>
img, canvas {
width: 125px;
}
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中的结果(来自视网膜显示屏的截图):
发生的事情是<img>
和<canvas>
都以相同的大小开始,并由浏览器按css缩小(图片宽度为783px)。显然,浏览器在<img>
上进行了一些很好的平滑/插值,但在<canvas>
上却没有。
我试过了:
image-rendering
,但默认值似乎已经是我想要的了。Context2D.imageSmoothingEnabled
,但是再一次,默认值描述了我想要的内容。如何让右侧的图像看起来像左侧的图像?最好用尽可能少的代码(例如,我自己不要实现双三次插值)。
答案 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);
}
结果:
在Windows 8.1上的Firefox 35.0.1上测试过。请注意,您当前的代码不处理浏览器缩放事件,这可能会重新引入像素化。您可以通过处理resize事件来解决此问题。
答案 1 :(得分:2)
Canvas并不意味着要进行css缩放:尝试过度采样:使用两倍所需的画布大小,css缩放在缩小画布时可以做得很好。
在hi-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>
答案 2 :(得分:0)
缩放画布并认为您解决了图像缩放问题并不是一个好主意。您可以将动态值传递给画布,然后根据需要绘制该尺寸。 这是canvas doc:http://www.w3docs.com/learn-javascript/canvas.html
的链接答案 3 :(得分:0)
简单回答,你不能这样做。画布就像一个位图,仅此而已。
我的想法: 您应该在缩放时重绘整个曲面,并确保缩放要绘制到画布的图像。因为它是矢量图形,所以应该可行。但是你肯定要重新绘制画布。