详解JavaScript+Canvas绘制环形进度条

 更新时间:2022年02月11日 15:41:19   作者:聆聽  
canvas可以在页面中设定一个区域,再利用JavaScript动态地绘制图像。本文将利用canvas绘制一个可以动的环形进度条。文中的示例代码讲解详细,感兴趣的小伙伴可以动手试一试

效果图

思考

移动端的场景里经常会出现环形进度条的功能,在实现这个功能前,我预想的解决方案大致有: echarts、antv、canvas、svg

前面两种第三方提供的解决方案当然是简单,拿到案例修整一下即可,但是需要下载依赖,而且代码量不小。有没有不需要依赖第三方包,采用原生的写法,独立封装成一个组件,降低耦合,而且性能优越?

当然,那就主要介绍canvas的使用

实现思路

可以展示整个圆、半圆以及任意角度弧形(左右对称)的进度条。整体思路如下:

1.先确定展示的形状,是整个圆、半圆还是一般的弧形

2.把确定好形状的圆弧均分100等份,计算出每一份所占的弧度

3.灰色圆弧占100份,红色圆弧最终占的份数由参数确定

4.设置setInterval定时器,重复执行画图操作

  • 清空画布
  • 先画灰色的圆弧,占100份
  • 再画红色的圆弧:红色圆弧的份数从0开始,每次加1
  • 画红色圆弧末端的红色圆:难点在于根据角度确定红色圆的圆心,这里面涉及到三角函数,在草稿纸上画个图就大致明白了
  • 当红色圆弧的份数达到指定值(传的参数)的时候,清除定时器

具体代码实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>Canvas</title>
</head>
<body>
  <canvas id="canvas" width="300" height="300"></canvas>

  <script>
    draw(66);
    /**
     * [顺时针方向画图,起始点在左侧]
     * @param  {[number]} percent [所占的进度百分比,比如66%,则传66即可,0 <= percent <= 100]
     * @param  {[number]} sR      [圆弧起始角度,可不传,默认是π/2,Math.PI/2 <= sR < 3/2 * Math.PI]
     */
    function draw(percent, sR) {
      if (percent < 0 || percent > 100) {
        return;
      }
      if (sR < Math.PI/2 || sR >= 3/2 * Math.PI) {
        return;
      }

      var canvas = document.querySelector('#canvas'),
          cxt = canvas.getContext('2d'),
          cWidth = canvas.width,
          cHeight = canvas.height,
          baseColor = '#e1e1e1',
          coverColor = '#fe4d43',
          PI = Math.PI,
          sR = sR || 1/2 * PI; // 默认圆弧的起始点弧度为π/2

      var finalRadian = sR + ((PI + (PI - sR) * 2) * percent / 100); // 红圈的终点弧度
      var step = (PI + (PI - sR) * 2)/100; // 一个1%对应的弧度大小
      var text = 0; // 显示的数字
      var timer = setInterval(function() {
        cxt.clearRect(0, 0, cWidth, cHeight);
        var endRadian =  sR + text * step;
        // 画灰色圆弧
        drawCanvas(cWidth/2, cHeight/2, 80, sR, sR + (PI + (PI - sR) * 2), baseColor, 2);
        // 画红色圆弧
        drawCanvas(cWidth/2, cHeight/2, 80, sR, endRadian, coverColor, 2);

        // 画红色圆头
        // 红色圆头其实就是一个圆,关键的是找到其圆心,涉及到三角函数知识,自己画个图一看就明了
        var angle = 2*PI - endRadian; // 转换成逆时针方向的弧度(三角函数中的)
        xPos = Math.cos(angle) * 80 + cWidth/2; // 红色圆 圆心的x坐标
        yPos = -Math.sin(angle) * 80 + cHeight/2; // 红色圆 圆心的y坐标
        drawCanvas(xPos, yPos, 2, 0, 2*PI, coverColor, 2);

        // 数字
        cxt.fillStyle = coverColor;
        cxt.font = '40px PT Sans';
        var textWidth = cxt.measureText(text+'%').width;
        cxt.fillText(text+'%', cWidth/2 - textWidth/2, cHeight/2 + 15);
        text++;

        if (endRadian.toFixed(2) >= finalRadian.toFixed(2)) {
          clearInterval(timer);
        }
      }, 30);

      function drawCanvas(x,y,r,sRadian,eRadian,color,lineWidth) {
        cxt.beginPath();
        cxt.lineCap = "round";
        cxt.strokeStyle = color;
        cxt.lineWidth = lineWidth;
        cxt.arc(x, y, r, sRadian, eRadian, false);
        cxt.stroke();
      }
    }
  </script>
</body>
</html>

关于动画部分,可以使用requestAnimationFrame做优化,函数改写如下:

function draw(percent, sR) {
  if (percent < 0 || percent > 100) {
    return;
  }
  if (sR < Math.PI/2 || sR >= 3/2 * Math.PI) {
    return;
  }

  var canvas = document.querySelector('#canvas'),
      cxt = canvas.getContext('2d'),
      cWidth = canvas.width,
      cHeight = canvas.height,
      baseColor = '#e1e1e1',
      coverColor = '#fe4d43',
      PI = Math.PI,
      sR = sR || 1/2 * PI; // 默认圆弧的起始点弧度为π/2

  var finalRadian = sR + ((PI + (PI - sR) * 2) * percent / 100); // 红圈的终点弧度
  var step = (PI + (PI - sR) * 2)/100; // 一个1%对应的弧度大小
  var text = 0; // 显示的数字

  window.requestAnimationFrame(paint);
  function paint() {
    cxt.clearRect(0, 0, cWidth, cHeight);
    var endRadian =  sR + text * step;
    // 画灰色圆弧
    drawCanvas(cWidth/2, cHeight/2, 80, sR, sR + (PI + (PI - sR) * 2), baseColor, 2);
    // 画红色圆弧
    drawCanvas(cWidth/2, cHeight/2, 80, sR, endRadian, coverColor, 2);

    // 画红色圆头
    // 红色圆头其实就是一个圆,关键的是找到其圆心,涉及到三角函数知识,自己画个图一看就明了
    var angle = 2*PI - endRadian; // 转换成逆时针方向的弧度(三角函数中的)
    xPos = Math.cos(angle) * 80 + cWidth/2; // 红色圆 圆心的x坐标
    yPos = -Math.sin(angle) * 80 + cHeight/2; // 红色圆 圆心的y坐标
    drawCanvas(xPos, yPos, 2, 0, 2*PI, coverColor, 2);

    // 数字
    cxt.fillStyle = coverColor;
    cxt.font = '40px PT Sans';
    var textWidth = cxt.measureText(text+'%').width;
    cxt.fillText(text+'%', cWidth/2 - textWidth/2, cHeight/2 + 15);
    text++;

    if (endRadian.toFixed(2) < finalRadian.toFixed(2)) {
      window.requestAnimationFrame(paint);
    }
  }

  function drawCanvas(x,y,r,sRadian,eRadian,color,lineWidth) {
    cxt.beginPath();
    cxt.lineCap = "round";
    cxt.strokeStyle = color;
    cxt.lineWidth = lineWidth;
    cxt.arc(x, y, r, sRadian, eRadian, false);
    cxt.stroke();
  }

到此这篇关于详解JavaScript+Canvas绘制环形进度条的文章就介绍到这了,更多相关JavaScript Canvas环形进度条内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • uniapp 动态组件实现Tabs标签切换组件(喜马拉雅app作为案例)

    uniapp 动态组件实现Tabs标签切换组件(喜马拉雅app作为案例)

    本文以喜马拉雅app作为案例给大家详解讲解uniapp 动态组件实现Tabs标签切换组件功能,在uniapp中实现动态组件切换需看uniapp是否支持,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-10-10
  • JavaScript前端实现压缩图片功能

    JavaScript前端实现压缩图片功能

    这篇文章主要介绍了JavaScript前端实现压缩图片功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • JS与Ajax Get和Post在使用上的区别实例详解

    JS与Ajax Get和Post在使用上的区别实例详解

    这篇文章主要介绍了JS与Ajax Get和Post在使用上的区别实例详解的相关资料,非常不错具有参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • 5个javascript的数字格式化函数分享

    5个javascript的数字格式化函数分享

    Javascript没有任何内建的格式化函数,这里我们通过Google收集了5个javascript的数字格式化函数,希望对于大家的web开发能够带来方便
    2011-12-12
  • fullpage.js全屏滚动的具体使用方法

    fullpage.js全屏滚动的具体使用方法

    fullPage.js 是一个基于 jQuery 的插件,它能够很方便、很轻松的制作出全屏网站,本文主要介绍了fullpage.js全屏滚动的具体使用方法,感兴趣的可以了解一下
    2021-09-09
  • 小程序实现图片预览裁剪插件

    小程序实现图片预览裁剪插件

    这篇文章主要为大家详细介绍了小程序实现图片预览裁剪插件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • 微信小程序获取手机网络状态的方法【附源码下载】

    微信小程序获取手机网络状态的方法【附源码下载】

    这篇文章主要介绍了微信小程序获取手机网络状态的方法,涉及微信小程序wx.getNetworkType函数检查网络连接状态的相关使用技巧,并附带源码供读者下载参考,需要的朋友可以参考下
    2017-12-12
  • javascript实现拖放效果

    javascript实现拖放效果

    这篇文章主要介绍了javascript实现拖放效果的相关资料,需要的朋友可以参考下
    2015-12-12
  • Bootstrap的Carousel配合dropload.js实现移动端滑动切换图片

    Bootstrap的Carousel配合dropload.js实现移动端滑动切换图片

    这篇文章主要介绍了bootstrap的Carousel配合dropload.js实现移动端滑动切换图片,实现方法非常简单,具有参考借鉴价值,需要的朋友可以参考下
    2017-03-03
  • JS+CSS实现的蓝色table选项卡效果

    JS+CSS实现的蓝色table选项卡效果

    这篇文章主要介绍了JS+CSS实现的蓝色table选项卡效果,通过鼠标事件调用自定义函数实现页面元素样式的遍历与动态切换效果,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10

最新评论