canvas绘制圆形动画圆角进度条

栏目: Html5 · 发布时间: 5年前

内容简介:如果不想看步骤的可以直接看最后面有完整的代码最近在做一个圆形的进度条,在网上看了一些例子有些地方不太理解,后来自己写了个一个分享一下先上一个最终的效果

如果不想看步骤的可以直接看最后面有完整的代码

最近在做一个圆形的进度条,在网上看了一些例子有些地方不太理解,后来自己写了个一个分享一下

先上一个最终的效果

canvas绘制圆形动画圆角进度条

首先画一整个圆

const cvsWitdh = 220
    const cvsHeight = 220

    const progess = 50 // 定义进度为50
    const maxPro = 100  // 定义总进度为100
    const r = 100 // 定义圆的半径为100
    this.cvs.width = cvsWitdh
    this.cvs.height = cvsHeight
    const ctx = this.cvs.getContext('2d')
    ctx.lineWidth = 10
    ctx.strokeStyle = '#15496B'
    ctx.arc(r + 10, r + 10, r, 0, 2 * Math.PI) 
    ctx.stroke() // 至此大圆画完

上面的代码需要注意的是 arc 方法的最后一侧参数是 弧度(2π) 不是角度,画圆的起点是 表的3点的位置开始画的不是12点位置

然后是画一个进度的圆弧

画圆弧度,主要是需要计算出 起点的弧度终点的弧度

ctx.beginPath()
    ctx.lineCap = 'round'
    // 下面是渐变的代码不需要的可以换成纯色
    let grd = ctx.createLinearGradient(0, 0, 220, 220)
    grd.addColorStop(0, 'red')
    grd.addColorStop(1, 'blue')
    ctx.strokeStyle = grd
    const startRadian = progress >= maxPro ? 0 : Math.PI * 1.5
    const rate = progress / maxPro
    const endRadian = progress >= maxPro ? 2 * Math.PI : 2 * Math.PI * rate - Math.PI / 2
    ctx.arc(r + 10, r + 10, r, startRadian, endRadian)
    ctx.stroke()

上面的代码中 ctx.lineCap = 'round' 这个是设置最终绘制的线是带圆角的

起点的弧度计算方式

const startRadian = progess >= maxPro ? 0 : Math.PI * 1.5

我们希望点的起点位置是钟表 12点钟 位置,整个圆的弧度是 2π==360° 推算得知12点钟的位置是 1.5π==270°

终点的弧度计算方式

const rate = progress / maxPro
  const endRadian = progress >= maxPro ? 2 * Math.PI : 2 * Math.PI * rate - Math.PI / 2

const rate = progress / maxProo 得值为进度占圆的比率

2π * rate 就是进度所需要的弧度

由于 arc 方法画圆的 起点是3点的方向 而我们的 起点是12点方向 所以我们还需要减掉一个 Math.PI / 2 最终就得出了我们上面的公式

由于当 progress等于maxPro 的时候算出来的终点等于我们的起点最终画的就会有问题,所以我们在计算起点终点的时候做了判断 progress >= maxPro 时画整圆

当前效果

canvas绘制圆形动画圆角进度条

动画实现

let currentProgress = 1
const timer = setInterval(() => {
      if (currentProgress >= progress) {
        currentProgress = progress
        clearInterval(timer)
      }
      ctx.beginPath()
      ctx.lineCap = 'round'
      // 下面是渐变的代码不需要的可以换成纯色
      let grd = ctx.createLinearGradient(0, 0, 220, 220)
      grd.addColorStop(0, 'red')
      grd.addColorStop(1, 'blue')
      ctx.strokeStyle = grd
      const startRadian = currentProgress >= maxPro ? 0 : Math.PI * 1.5
      const rate = currentProgress / maxPro
      const endRadian = currentProgress >= maxPro ? 2 * Math.PI : 2 * Math.PI * rate - Math.PI / 2
      ctx.arc(r + 10, r + 10, r, startRadian, endRadian)
      ctx.stroke()
      currentProgress++
    }, 10)

动画的实现也非常的简单,我们只需定义一个临时的进度 currentProgress 通过定时器每次累加这个进度知道与 progress 相等停止计时,期间每次绘制

完整的代码

我用react 写的所以直接把react的整个代码粘过来了,如果不需要的可以只拿绘图的那一部分

import React from 'react'

export default class Test extends React.Component {
  componentDidMount () {
    this.renderProgress(30)
  }

  renderProgress (progress) {
    const cvsWitdh = 220
    const cvsHeight = 220
    const maxPro = 100  // 定义总进度为100
    const r = 100 // 定义圆的半径为100
    this.cvs.width = cvsWitdh
    this.cvs.height = cvsHeight
    const ctx = this.cvs.getContext('2d')
    ctx.lineWidth = 10
    ctx.strokeStyle = '#15496B'
    ctx.arc(r + 10, r + 10, r, 0, 2 * Math.PI) // 2 * Math.PI === 360 度 最后一个参数代表的是圆的弧度
    ctx.stroke() // 至此大圆画完
    if (progress === 0) {
      return
    }
    let currentProgress = 1
    const timer = setInterval(() => {
      if (currentProgress >= progress) {
        currentProgress = progress
        clearInterval(timer)
      }
      ctx.beginPath()
      ctx.lineCap = 'round'
      // 下面是渐变的代码不需要的可以换成纯色
      let grd = ctx.createLinearGradient(0, 0, 220, 220)
      grd.addColorStop(0, 'red')
      grd.addColorStop(1, 'blue')
      ctx.strokeStyle = grd
      const startRadian = currentProgress >= maxPro ? 0 : Math.PI * 1.5
      const rate = currentProgress / maxPro
      const endRadian = currentProgress >= maxPro ? 2 * Math.PI : 2 * Math.PI * rate - Math.PI / 2
      ctx.arc(r + 10, r + 10, r, startRadian, endRadian)
      ctx.stroke()
      currentProgress++
    }, 10)
  }

  render () {
    return (
      <div>
        <br />
        <br />
        <canvas
          ref={ref => {
            this.cvs = ref
          }}
        />

        <br />

        <br />
        <button onClick={() => {
          this.renderProgress(60)
        }}>重新loadprogress</button>
      </div>
    )
  }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数字乌托邦

数字乌托邦

[美]弗雷德·特纳 / 张行舟、王芳、叶富华、余倩 / 译言·东西文库/电子工业出版社 / 2013-5-1 / 49.80元

20世纪60年代早期,在美国大众眼中,计算机只是冷战中冰冷的机器,然而到了90年代互联网到来之时,计算机却呈现出一个截然不同的世界——它们模拟出了一个数字乌托邦般的协同体,而这正是曾经最反对冷战的嬉皮士们的共同愿景。 本书正是探索这次非同寻常,且颇具讽刺意味的变革的第一本书。作者挖掘出那些在旧金山湾区的先驱者——斯图尔特·布兰德和他的“全球网络”鲜为人知的故事。1968年到1998年期间,通......一起来看看 《数字乌托邦》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具