如果你只需要縮放文本,你可以簡單地縮放字體大小。
上但有兩點要注意:字體,或字體,不只是簡單的規模意味着你不會得到順利進行。這是因爲字體通常針對特定尺寸進行了優化,所以可以說這些尺寸之間的尺寸是前一個尺寸和下一個尺寸的結果。這可以使字體看起來像是在擴大規模時正在移動,並且是正常的和預期的。
這裏的方法使用簡單的尺寸比例。如果你需要一個絕對平滑的比例尺用於動畫目的,你將不得不使用一種非常不同的技術。
簡單的方法是:
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