HTML5画布支持基于浏览器的缩放吗?

18
我已经设置了一个简单的画布,上面绘制了fillText。它看起来很好,但当我使用浏览器提供的缩放功能(Safari,Firefox)时,抗锯齿效果看起来很丑陋。
我尝试使用scale()来提高网格密度,但没有帮助。
有没有办法在画布上绘制图形,使其即使在缩放后的浏览器窗口中也能保持清晰?
屏幕截图(无缩放): http://i.stack.imgur.com/CGWka.png 屏幕截图(最大缩放):http://i.stack.imgur.com/vNPjF.png
2个回答

22

在绘制命令之前缩放画布上下文,可以通过“缩放”canvas来使绘制的物品以更大的尺寸平滑地绘制。例如,请参见我的这个例子,它允许您缩放绘制项并查看默认演示中无法显示的细节。

浏览器缩放的问题在于HTML5 canvas——就像JPG或PNG和不像SVG那样——基于单独的像素。如果你用10个像素画一个圆,然后告诉浏览器将其缩放到50个像素,浏览器无法“创造”数据以绘制平滑的圆形。最好的方法是提供图像插值,试图使“大像素”看起来稍微平滑一些。

解决方案

对于图像,您可以拍摄具有大量像素(例如1000x800)的照片,并告诉浏览器以不同的较小尺寸(例如250x200)显示它。当浏览器缩放时,它会有更多的像素来显示。例如:

<img src="1000x800.jpg" style="width:250px; height:200px">
你可以使用画布来实现相同的效果。画布中的像素数由heightwidth属性(在HTML或JavaScript中)指定。您可以单独将CSS 显示大小(如上所示)指定为较小的尺寸。您甚至不需要修改您现有的画布绘制代码; 只需执行以下操作:
  1. 按特定因子(例如4)调整画布的heightwidth
  2. 使用CSS将显示高度和宽度设置回原始大小,然后
  3. 在所有其他绘图命令之前,使用ctx.scale(4,4)扩大您的上下文。
编辑: 我已经在这里创建了一个例子:
http://jsfiddle.net/u5QPq/embedded/result/ (代码)
当您放大时,它看起来像这样:
enter image description here 作为额外的奖励,您的画布还将更顺畅地打印(以防有人想砍树)。

1
@st4rbuck 不用谢。请注意,如果这个答案解决了你的问题,你应该“接受”它:点击大的勾号 - Phrogz
@Phrogz:非常感谢您提供这个有用的示例。我遇到了一个可能相关的问题,希望能指导我找到解决方案。我使用ng-signature-pad(基于画布)来捕获签名(涂鸦为基础)。问题在于,如果浏览器不是100%缩放,绘图区域会混乱,当我在缩放不是100%的情况下上传现有图像(使用FileReader)到画布上时,图像看起来很奇怪或被截断。我该如何解决这个问题? - tarekahf
@tarekahf 你应该将这个发帖作为一个问题,而不是在一个(相关但不同的)问题答案下进行评论。 - Phrogz
@Phrogz:我在这里添加了问题(http://stackoverflow.com/questions/40514118/funny-behaviour-with-ng-signature-pad-canvas-used-to-capture-scribble-signatur)。希望不会有人给负评! - tarekahf
这不是一个好的解决方案。这意味着大多数时间你将以比必要更高的分辨率进行渲染,并且你必须选择一个任意的缩放上限。DewiW的答案要好得多。 - Timmmm

4
简短的回答是不行,canvas元素不会自动支持基于浏览器的缩放,也就是说,当你缩放时,你的canvas元素会看起来很丑。你的浏览器只能绘制已经存在的细节。
然而,在桌面端使用浏览器缩放时,会发生以下三件事情:
  1. window.devicePixelRatio值会改变以反映新的物理像素比例。
  2. 报告的宽度和高度 (window.innerWidthwindow.innerHeight) 会相应地更改。
  3. onresize事件被触发。
这意味着你可以监听onresize事件,并根据新的像素比率和显示大小重新创建你的canvas。在桌面端,这将为你提供一个始终清晰的canvas元素,而无需以比所需分辨率更高的分辨率绘制canvas元素。 codepen proof of concept 我还在Medium上写了一篇文章,详细介绍了这种方法以及其他可用于使画布元素更易于被视力较差的人使用的技术: HTML画布和无障碍性
不幸的是,移动/平板电脑的捏合缩放功能略有不同,这种方法在那里不起作用。如果有人有适用于捏合缩放的替代方法,我很想听听!

谢谢分享这个。就我所理解的,这个例子中的绘图是在目标缩放级别下执行的(考虑到 devicePixelRatio),然后通过 CSS 转换为不同的大小,然后浏览器再次将其缩放到目标大小。是这样吗?这意味着会始终存在缩放伪影,因为画布被缩放了两次。我是对的吗? - carlfriedrich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接