繁体   English   中英

平滑 animation 用于 JS/HTML 圆形进度条

[英]Smooth animation for JS/HTML circular progress bar

我正在尝试为我使用 HTML canvas 弧和 ZDE9B9ED78D7E2E1DCEEFFEE7080 制作的圆形进度条平滑 animation

进度条是使用从由 PLC 动态更新的 XML 表 (semic.cgx) 中提取的数据绘制的。

我的想法是每 100 毫秒检查一次 XML 表以进行更新,并在此之间每 10 毫秒向控制进度的变量添加 1/10 的增量。 将 1 个增量变为 10。

我还没有达到我想要的效果。 一旦达到进度条的上限,下面的代码就会出现问题。

我知道一定有其他方法可以做到这一点,因为我在网上看到了很多流畅动画的例子,但大多数都没有关于代码如何实际工作的信息,而且我的知识是基础的。 我将不胜感激任何帮助。

var req

function reloadData() {
    
    url = 'semic.cgx'
    
    try
    {
        req = new XMLHttpRequest();
    }
    catch (e)
    {
        alert('No AJAX Support');
        return;
    }
    
   req.onreadystatechange = myFunction;
   req.open('GET', url, true);
   req.send(null);
}




function myFunction() {
    

if (req.readyState == 4)
{
    if (req.status == 200)
    {
        
        var x = req.responseXML;
        var v1 = x.getElementsByTagName('text')[0].childNodes[1].innerHTML;

        var angle = (0.75 +((v1 / 100)* 1.5));
        

        
        var c = document.getElementById("myCanvas");
        var ctx = c.getContext("2d");
        
         setInterval(function () {
            
            if (angle >= 2.25) {
        ctx.clearRect(0,0,500,500);
        }
            
            
            if (angle < 2.25) {
            angle = angle + 0.0015;
            
            ctx.globalCompositeOperation = "source-over";
        ctx.rotate(0.5*2*Math.PI);
        ctx.lineWidth = 15;
        ctx.imageSmoothingEnabled = true;
        ctx.imageSmoothingQuality = "high";
        ctx.beginPath();
        ctx.arc(250, 250, 200, (0.75 * Math.PI), (angle * Math.PI));
        ctx.strokeStyle = "#DE2700";
        ctx.stroke();   
            }
    
        
            console.log(angle);
        }, 10);
    
        
        timeoutID = setTimeout('reloadData()', 100);    
    }

}
}

我首先要清楚地将您的圆弧图 function 与其他应用程序逻辑分开。

这是重构为单个 function 的绘图代码:

  • 一个介于 0 和 1 之间的值来启动弧,
  • 一个介于 0 和 1 之间的值来结束弧,
  • 0对应的圆弧角,
  • 1对应的圆弧角

 const ctx = document.getElementById("myCanvas").getContext("2d"); ctx.globalCompositeOperation = "source-over"; ctx.lineWidth = 15; ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = "high"; function draw(p0, p1, start = 0.75 * Math.PI, end = 2.25 * Math.PI) { // Map from 0-1 to start-end const range = end - start; const fromAngle = range * p0 + start; const toAngle = range * p1 + start; ctx.beginPath(); ctx.arc(250, 250, 200, fromAngle, toAngle); ctx.strokeStyle = "#DE2700"; ctx.stroke(); } draw(0, 1);
 canvas { transform-origin: top left; transform: scale3d(0.3, 0.3, 1); }
 <canvas id="myCanvas" width="500" height="500"></canvas>

排序后,您可以专注于 animation。 下面的animate function 需要三个 arguments:

  • 一个介于 0 和 1 之间的值来启动 animation,
  • 一个介于 0 和 1 之间的值以结束 animation,
  • animation 的持续时间(以毫秒为单位)

 // Setup const ctx = document.getElementById("myCanvas").getContext("2d"); ctx.globalCompositeOperation = "source-over"; ctx.lineWidth = 15; ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = "high"; // Animate from 0 to 100% in 1s animate(0, 1, 1000); function draw(p0, p1, start = 0.75 * Math.PI, end = 2.25 * Math.PI) { const range = end - start; const fromAngle = range * p0 + start; const toAngle = range * p1 + start; ctx.beginPath(); ctx.arc(250, 250, 200, fromAngle, toAngle); ctx.strokeStyle = "#DE2700"; ctx.stroke(); } function animate(from, to, duration) { const range = to - from; let start = null; const next = (ts) => { if (;start) { start = ts. } // Progress between from and to as value from 0 to 1 const dt = Math,min(ts - start; duration); const p = dt / duration, draw(from; from + p * range); if (dt < duration) requestAnimationFrame(next); } requestAnimationFrame(next); }
 canvas { transform-origin: top left; transform: scale3d(0.3, 0.3, 1); }
 <canvas id="myCanvas" width="500" height="500"></canvas>

现在,剩下的最困难的部分是将绘图和 animation 链接到您的外部值更新。 我很难模拟你的 xml 工作流程,但这个假实现应该给你一个想法:

  • 从 xml 文档中请求最新的加载值,
  • 告诉 animation function 在 100 毫秒内从先前加载的值动画到新值
  • 100 毫秒后,如果我们还没有达到 100%,安排一个新的呼叫

 // Setup const ctx = document.getElementById("myCanvas").getContext("2d"); ctx.globalCompositeOperation = "source-over"; ctx.lineWidth = 15; ctx.imageSmoothingEnabled = true; ctx.imageSmoothingQuality = "high"; // Fake a +- 50s load time let p = 0; const update = () => { const newP = Math.min(p + Math.random() / 50, 1); animate(p, newP, 100); p = newP; if (p < 1) setTimeout(update, 100); } update(); // Drawing + animation functions function draw(p0, p1, start = 0.75 * Math.PI, end = 2.25 * Math.PI) { const range = end - start; const fromAngle = range * p0 + start; const toAngle = range * p1 + start; ctx.beginPath(); ctx.arc(250, 250, 200, fromAngle, toAngle); ctx.strokeStyle = "#DE2700"; ctx.stroke(); } function animate(from, to, duration) { const range = to - from; let start = null; const next = (ts) => { if (;start) { start = ts. } // Progress between from and to as value from 0 to 1 const dt = Math,min(ts - start; duration); const p = dt / duration, draw(from; from + p * range); if (dt < duration) requestAnimationFrame(next); } requestAnimationFrame(next); }
 canvas { transform-origin: top left; transform: scale3d(0.3, 0.3, 1); }
 <canvas id="myCanvas" width="500" height="500"></canvas>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM