簡體   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