如果你只需要缩放文本,你可以简单地缩放字体大小。
上但有两点要注意:字体,或字体,不只是简单的规模意味着你不会得到顺利进行。这是因为字体通常针对特定尺寸进行了优化,所以可以说这些尺寸之间的尺寸是前一个尺寸和下一个尺寸的结果。这可以使字体看起来像是在扩大规模时正在移动,并且是正常的和预期的。
这里的方法使用简单的尺寸比例。如果你需要一个绝对平滑的比例尺用于动画目的,你将不得不使用一种非常不同的技术。
简单的方法是:
ctx.font = (fontSize * scale).toFixed(0) + 'px sans-serif';
的online demo here。
出于动画目的,你需要做到以下几点:
- 渲染更大尺寸的屏幕外的画布上,然后用来绘制不同尺寸
- 当差值过大,你会遇到内插问题,你将不得不以密钥大小渲染这些缓存文本图像中的几个,以便在缩放因子超过某个阈值时可以在它们之间切换。
In this demo你可以看到,在小尺寸的像素变得有点“块状”但在其他方面是比纯文本方式更加顺畅。
这是因为浏览器使用双线性插值而不是使用双立方体与画布(这可能会或可能不会在将来改变),所以当差异变大时它不能正确插值(请参阅下面的解决方案与这个问题)。
相反的情况发生在大尺寸的情况下,由于插值,文字变得模糊。
这是我们不得不切换到更小(或更大)缓存版本的地方,然后在我们再次切换之前在一定范围内进行缩放。
该演示简化为仅显示单个缓存版本。你可以看到一半,这工作正常。原理将采用完整的解决方案(尺寸仅为示例):
(更新Here is a demo在缩放期间的切换图像)。
-- Cached image (100px)
-- Draw cached image above scaled based on zoom between 51-100 pixels
-- Cached image (50px) generated from 100px version/2
-- Draw cached image above scaled based on zoom between 26-50 pixels
-- Cached image (25px) generated from 50px version/2
-- Draw cached image above scaled based on zoom between 1-25 pixels
然后用“甜蜜点”(你通过实验一点点找到),把他们拉来筛选前的缓存版本之间切换。
var ctx = canvas.getContext('2d'),
scale = 1, /// initial scale
initialFactor = 6, /// fixed reduction scale of cached image
sweetSpot = 1, /// threshold to switch the cached images
/// create two off-screen canvases
ocanvas = document.createElement('canvas'),
octx = ocanvas.getContext('2d'),
ocanvas2 = document.createElement('canvas'),
octx2 = ocanvas2.getContext('2d');
ocanvas.width = 800;
ocanvas.height = 150;
ocanvas2.width = 400; /// 50% here, but maybe 75% in your case
ocanvas2.height = 75; /// experiment to find ideal size..
/// draw a big version of text to first off-screen canvas
octx.textBaseline = 'top';
octx.font = '140px sans-serif';
octx.fillText('Cached text on canvas', 10, 10);
/// draw a reduced version of that to second (50%)
octx2.drawImage(ocanvas, 0, 0, 400, 75);
现在,我们只需要检查甜蜜点值,找出什么时候这些版本之间切换:
function draw() {
/// calc dimensions
var w = ocanvas.width/initialFactor * scale,
h = ocanvas.height/initialFactor * scale;
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (scale >= sweetSpot) {
ctx.drawImage(ocanvas, 10, 10, w, h); /// use cached image 1
} else {
ctx.drawImage(ocanvas2, 10, 10, w, h); /// use cached image 2
}
}
那么为什么不直接绘制第二缓存的图片与字体?你可以做到这一点,但随后你又回到了字体为特定大小进行优化的问题,并且在缩放时会产生一个小小的跳跃。如果你能忍受这一点,那么使用它,因为它会提供更好的质量(特别是小尺寸)。如果你需要流畅的动画,你将不得不减小一个更大的缓存版本,以保持100%的比例。
你可以看到this answer关于如何在没有内插问题的情况下调整大图像大小。
希望这会有所帮助。
如何缩放画布?你在谈论Web浏览器的内置缩放功能吗(Ctrl +鼠标滚轮)?还是你编程自己的缩放功能?当你完成后者时,你是如何实现它的?您是以更大规模绘制还是使用CSS调整画布大小? – Philipp
我试着用CTRL + moueswheel,是否有更简洁的方式来实现画布缩放? @Philipp – Basj
为了减少像素化,你将不得不听取大小调整事件。调整大小时,您必须缩放ctx.font(向上/向下)并重新绘制画布。 – markE