[英]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 的繪圖代碼:
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:
// 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 工作流程,但這個假實現應該給你一個想法:
// 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.