[英]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.