返回

利用 Canvas 巧妙实现环形进度条

前端

在移动端的广阔天地里,环形进度条已成为一种不可或缺的功能性元素。它的妙用随处可见,从监测下载进度到展示任务完成率,它都能以直观且吸引人的方式传达信息。

当着手实现这一功能时,我们自然会考虑多种方案,其中包括:

  • 第三方库: 如 ECharts、AntV 等,它们提供了现成的环形进度条组件,只需稍加配置即可。这种方式简单便捷,但定制性和灵活性受限。
  • Canvas: HTML5 中的原生绘图技术,它赋予开发者完全的控制权,可以绘制任何形状和动画。
  • SVG: 可缩放矢量图形,使用 XML 定义图形,优点是轻量、清晰且支持动画。

在权衡利弊之后,我选择了 Canvas,因为它在定制性、性能和跨平台兼容性方面都具有优势。接下来,让我们深入了解如何利用 Canvas 轻松实现环形进度条。

理解环形进度条

环形进度条本质上是一个圆形,其中一部分被填充以表示进度。为了准确绘制它,我们需要确定圆心、半径和填充角度。

1. 圆心

圆心是环形进度条的中心点,通常位于画布的中间位置。

2. 半径

半径是圆的长度,从圆心到圆周的距离。

3. 填充角度

填充角度表示已完成进度的弧度,以度为单位。

绘制环形进度条

有了这些基础知识,我们就可以着手绘制环形进度条了:

  1. 创建画布: 使用 <canvas> 元素创建一个 HTML 画布。
  2. 获取画布上下文: 使用 getContext() 方法获取画布的绘图上下文。
  3. 确定圆心: 计算圆心的位置,通常是画布宽高的中间点。
  4. 设置线条样式: 设置线条宽度、颜色和线帽。
  5. 绘制弧形: 使用 arc() 方法绘制弧形,指定圆心、半径、起始角度和填充角度。
  6. 填充弧形: 使用 fill() 方法填充弧形,使其可见。

设置动画

为了让进度条动起来,我们需要设置动画:

  1. 创建动画循环: 使用 requestAnimationFrame() 函数创建一个动画循环,不断更新进度条。
  2. 更新填充角度: 在动画循环中,根据当前进度更新填充角度。
  3. 重绘环形进度条: 使用 clearRect() 方法清除画布,然后重新绘制环形进度条以反映更新后的填充角度。

实例

下面是一个使用 Canvas 实现环形进度条的简单实例:

<canvas id="progress-bar"></canvas>
const canvas = document.getElementById("progress-bar");
const ctx = canvas.getContext("2d");

// 圆心
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;

// 半径
const radius = Math.min(centerX, centerY);

// 起始角度
const startAngle = 0;

// 填充角度
let progressAngle = 0;

function drawProgressBar() {
  // 清除画布
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  // 设置线条样式
  ctx.lineWidth = 10;
  ctx.strokeStyle = "#ccc";
  ctx.lineCap = "round";

  // 绘制未完成部分
  ctx.beginPath();
  ctx.arc(centerX, centerY, radius, startAngle, Math.PI * 2, false);
  ctx.stroke();

  // 设置线条样式
  ctx.strokeStyle = "#000";

  // 绘制已完成部分
  ctx.beginPath();
  ctx.arc(centerX, centerY, radius, startAngle, progressAngle, false);
  ctx.stroke();

  // 更新进度
  progressAngle += 0.01;
  if (progressAngle >= Math.PI * 2) {
    progressAngle = 0;
  }

  // 循环动画
  requestAnimationFrame(drawProgressBar);
}

drawProgressBar();

结语

掌握了利用 Canvas 实现环形进度条的技巧后,你就能轻松地在移动端项目中添加这一实用且美观的元素。它的高度定制性和动画效果让你可以创建出符合特定需求和视觉审美的进度条。快去尝试一下吧!