Web 前端开发

一步一步去实现一个环形进度条

2017-12-31  本文已影响0人  cb12hx

有这么个环形进度条,应该怎么去实现呢


image.png

从结构来看,需要一根背景线,一个进度线,一个百分比进度条,ok,一步步来看怎么实现

1.画背景线

这个比较简单,直接arc一下, 然后stroke一下即可,看看代码

  var c1 = document.querySelector('#c1')
  var ctx = c1.getContext('2d')
  ctx.translate(c1.width / 2, c1.height / 2)
  ctx.arc(0, 0, 100, 0, Math.PI * 2)
  ctx.lineWidth = 5
  ctx.stroke()
  ctx.beginPath()

translate将画笔放到canvas的中心,然后画一个圆,设置线的宽度为5,然后进行描边,之后开启一段新路径

2.画百分比进度条

其实这个也比较简单,只需要设置一下进度条的宽度,颜色,和圆弧的长度即可

  ctx.arc(0,0,100,0,60*Math.PI/180)
  ctx.lineWidth=10
  ctx.strokeStyle = 'red'
  ctx.stroke()

这段代码画了一条圆弧,长度为60度的角对应的弧长,设置弧宽为10,设置弧的颜色为红色,然后开始描边,看看效果


image.png

可以看出,一般情况下,我们需要弧的起点终点是圆的,这里用到了一个api,lineCap,它有三个取值

ctx.lineCap = "butt";
ctx.lineCap = "round";
ctx.lineCap = "square";

具体的请参阅这里,此处我们去round

image.png

3.画中间的百分比

这个也比较简单,先来看看代码

  ctx.beginPath()
  ctx.font = '30px Arial'
  ctx.fillText(parseFloat((60 / 360) * 100).toPrecision(2) + '%', -20, 10)

效果如下


image.png

这样的基本的环形百分比就画好了,注意设置font时,要同时传font-size和font-family,不然没有效果

4.添加动画

js中使用动画可以有setTimeout,setInterval,requestAnimationFrame,demo中用到的是第三个,因为它会自动的去算1000中执行多少帧,从而能够平滑地做动画;这里要注意的一点就是,画进度时,要先使用clearRect去除上一次的进度,不然会有一坨数字叠加。这里跟canvas的关系不大,就不一句一句解释了,贴出全部代码吧,直接保存为html即可看到具体效果

<html>

<head>
  <meta charset="utf-8">
  <title>文档标题</title>
  <!-- 开启响应式 -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- SEO页面关键词 -->
  <meta name="keywords" content="your keywords">
  <!-- SEO页面描述 -->
  <meta name="description" content="your description">
  <style>
  * {
    margin: 0;
    padding: 0;
  }

  #c1 {
    display: block;
    margin: 10px auto;
    border: 1px solid red;
    width: 300;
    height: 300;
  }
  </style>
</head>

<body>
  <canvas width="600" height="600" id="c1"></canvas>
  <script type="text/javascript">
  var c1 = document.querySelector('#c1')
  var ctx = c1.getContext('2d')
  ctx.translate(c1.width / 2, c1.height / 2)
  ctx.arc(0, 0, 100, 0, Math.PI * 2)
  ctx.lineWidth = 5
  ctx.stroke()
  ctx.beginPath()

  var currentAngle = 0
  var currentProcess = 0
  var currentPercentage = 0

  function process(endAngle) {
    var step = Math.PI / 60
    if (currentAngle + step > endAngle) {
      currentAngle = endAngle
    } else {
      currentAngle += step
    }
    ctx.beginPath()
    ctx.arc(0, 0, 100, 0, currentAngle)
    ctx.lineCap = 'round'
    var lingrad = ctx.createLinearGradient(0, 0, 0, 150);
    lingrad.addColorStop(0, '#f00');
    lingrad.addColorStop(1, '#ff0');
    ctx.lineWidth = 20
    ctx.strokeStyle = lingrad
    ctx.stroke()
    ctx.beginPath()

    currentProcess = (parseFloat(currentAngle / endAngle) * 100).F(2)
    ctx.clearRect(-50, -50, 120, 100)
    ctx.font = '30px Arial'
    ctx.fillText((parseFloat(+currentAngle / (Math.PI * 2))*100).toPrecision(2) + '%', -30, 5)
    if (currentAngle >= endAngle) {
      currentProcess = 1
      currentAngle = endAngle
      return
    }
    requestAnimationFrame(() => {
      process(endAngle)
    }, 100)
  }
  process(Math.PI * 1 / 3)
  </script>
</body>

</html>
上一篇下一篇

猜你喜欢

热点阅读