繁体   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