簡體   English   中英

如何制作 HTML5 Canvas 縮放動畫

[英]How to do a HTML5 Canvas scale animation

我正在開發一個畫布白板工具。 現在我正在處理放大和縮小功能。

到目前為止這工作正常,但現在我喜歡為縮放制作平滑的動畫。 但似乎它太快了,我看不到任何效果。 我單擊 + 或 - 按鈕並按比例縮放。

let scaleAmount = 1.00;

function scaleUpdate()
{
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.scale(scaleAmount, scaleAmount)   
    
    scaleSize.innerText = parseInt(parseFloat(scaleAmount.toFixed(2))*100)+"%";

    stageUpdate();  
   
}

function scale(direction)
{
    let scaleSize = document.getElementById("scaleSize");
    
    if(direction=="zoomIn")
    { 
        for(let i = 0; i<10; i++)
        {
            scaleAmount += 0.01;
            scaleAmount = parseFloat(scaleAmount.toFixed(2));
            dx += scaleAmount;
            dy += scaleAmount;   
            
            scaleUpdate();
        }
    }
    if(direction=="zoomOut")
    {
        for(let i = 0; i<10; i++)
        {
            scaleAmount -=0.01;
            scaleAmount = parseFloat(scaleAmount.toFixed(2));
            dx -= scaleAmount;
            dy -= scaleAmount;
            scaleUpdate();
        }
    }
}

dxdy是屏幕偏移量。

有人可以幫我解決這個問題嗎?

提前感謝弗蘭克

如果您在 for 循環中更新諸如比例尺之類的視覺屬性,它實際上會發生一次——這不是真的,但比眼睛快得多。 屏幕不會隨着 for 循環的每次迭代而更新。 這更像是在調用scale()函數之前和完成之后(也不是真的,但你明白了)。

要使這些更改可見,您需要隨着時間的推移進行操作。 例如,在開始時間 1.0 將比例設置為 1,在 1.1 將其設置為 1.01,在 1.2 將其設置為 1.02,依此類推,直到達到您的目標比例。 這可以通過使用setInterval()requestAnimationFrame()函數來完成。 setInterval 有兩個參數,要調用的函數和調用此函數的時間(以毫秒為單位)。 requestAnimationFrame 嘗試以顯示器的刷新率調用提供的函數 - 因此,如果它是 60hz 顯示器,它將被調用接近每秒 60 次。

如果我們修改您的示例以利用 requestAnimationFrame 函數:

 let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); document.getElementById("scaleUp").onclick = () => { cancelAnimationFrame(animationID); scale("zoomIn"); } document.getElementById("scaleDown").onclick = () => { cancelAnimationFrame(animationID); scale("zoomOut"); } let scaleAmount = 1.0; let animationID; function scale(direction) { let animationReady = false; let targetScale; if (direction == "zoomIn") { scaleAmount += 0.01; targetScale = 2; animationReady = scaleAmount >= targetScale; } if (direction == "zoomOut") { scaleAmount -= 0.01; targetScale = 1; animationReady = scaleAmount <= targetScale; } if (animationReady) { scaleAmount = targetScale; } else { animationID = requestAnimationFrame(() => { scale(direction); }); } stageUpdate(); } function stageUpdate() { ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.translate(canvas.width / 2, canvas.height / 2); ctx.scale(scaleAmount, scaleAmount); ctx.beginPath(); ctx.arc(0, 0, 45, 0, 2 * Math.PI); ctx.closePath(); ctx.stroke(); } stageUpdate();
 <button id="scaleUp" type="button">Scale +</button><button id="scaleDown" type="button">Scale -</button><br><canvas id="canvas" width="320" height="200"></canvas>

@obscure 你的回答真的很有幫助,謝謝。

我的最終代碼如下所示:

let scaleAmount = 1.00;
let scaleAnimation;
let animationReady = false;
let scalePercent =  parseInt(scaleSize.innerText.replace("%",""));
function scaleUpdate()
{
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.scale(scaleAmount, scaleAmount)   
    
    scaleSize.innerText = parseInt(parseFloat(scaleAmount.toFixed(1))*100)+"%";

    stageUpdate();  
   
}

function scale(direction)
{
    
    
    let targetScale ;

    if(direction=="zoomIn")
    { 
            targetScale = scalePercent / 100 + 0.1;
            
            scaleAmount += 0.01;
        
            animationReady = scaleAmount > targetScale;
            targetScale= parseFloat(targetScale.toFixed(3));
            scaleAmount = parseFloat(scaleAmount.toFixed(3));
            dx += scaleAmount;
            dy += scaleAmount;   
    }
    if(direction=="zoomOut")
    {
            targetScale = scalePercent / 100 - 0.1;

            scaleAmount -= 0.01;
           
            animationReady = scaleAmount < targetScale;
            targetScale= parseFloat(targetScale.toFixed(3));
            scaleAmount = parseFloat(scaleAmount.toFixed(3));
            dx -= scaleAmount;
            dy -= scaleAmount;
    }
 
    if (animationReady) {
        scaleAmount = targetScale;
        scalePercent =  parseInt(scaleSize.innerText.replace("%",""));
    } else {
        scaleAnimation = requestAnimationFrame(() => {
            scaleUpdate();
            scale(direction);
         });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM