使用CSS来优雅地缩放画布
使用CSS来优雅地缩放画布
我试图在画布上绘制一幅图像,然后使用CSS将画布调整到特定的大小。结果发现许多浏览器无法很好地缩小画布。OS X上的Firefox似乎是最糟糕的之一,但我没有测试很多。以下是问题的最小示例:
HTML
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中的结果(从Retina显示器的屏幕截图):
问题是和
都以相同的大小开始,并由浏览器使用CSS进行缩小(图像宽度为783px)。显然,浏览器对
进行了一些平滑/插值处理,但对
没有进行处理。
我尝试过:
image-rendering
,但默认值似乎已经是我想要的。- 诸如分步缩小图像之类的笨拙解决方案,但这并没有帮助:http://codepen.io/ford/pen/emGxrd。
Context2D.imageSmoothingEnabled
,但再一次,默认值描述了我想要的效果。
我如何使右侧的图像看起来像左侧的图像?最好尽可能少的代码(例如,我不想自己实现双三次插值)。
问题的出现原因是Canvas不适合使用CSS缩放,解决方法是通过过采样来达到缩放效果。在高分辨率设备上,应该再次增加分辨率以达到相同的质量。
代码如下:
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); }
CSS样式如下:
img, canvas { width: 125px; }
HTML代码如下:
然而,过采样的价格也是需要考虑的。以更好的图像质量为代价,需要使用2倍或4倍的画布。而在最需要这种高分辨率的设备上,比如移动设备,这种代价可能是最昂贵的。在我看来,过采样是一个不划算的选择,更好的方法是根据媒体查询创建多个预定大小的图像。
另外,通过适当的软件手动缩小图像将提供更好的效果并减少电池消耗。加载图像后,也可以使用正确的代码将图像缩小。但如果我们遵循提问者的要求:“尽可能少的代码”,我只能看到这个解决方案。
问题的出现原因:canvas元素在高分辨率屏幕上显示时,会出现像素模糊的问题。
解决方法:通过使用CSS对canvas进行缩放,以解决像素模糊的问题。具体做法是通过window.devicePixelRatio
属性来缩放canvas的绘图上下文,然后将图片绘制在缩放后的canvas上。
代码示例:
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); }
测试结果:
需要注意的是,当前的代码没有处理浏览器缩放事件,可能会导致再次出现像素模糊的问题。可以通过处理resize事件来解决这个问题。
在使用CSS对画布进行缩放时,可能会遇到一些问题。虽然这种方法能够解决图像缩放的问题,但并不是一个好的解决方案。相反,我们可以将动态值传递给画布,并根据需要绘制出相应大小的图像。
在下面的链接中,我们可以找到有关画布的详细文档:http://www.w3docs.com/learn-javascript/canvas.html。
解决这个问题的方法是将动态值传递给画布,并使用该值绘制所需大小的图像。以下是一个示例代码,展示了如何使用CSS对画布进行缩放:
var canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); // 获取动态值 var dynamicValue = 100; // 设置画布的宽度和高度 canvas.width = dynamicValue; canvas.height = dynamicValue; // 绘制图像 context.drawImage(image, 0, 0, dynamicValue, dynamicValue);
通过将动态值传递给画布的宽度和高度,我们可以根据需要缩放画布并绘制图像。这种方法可以确保画布按照所需大小进行缩放,而不会引起其他问题。