资讯专栏INFORMATION COLUMN

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

springDevBird / 996人阅读

摘要:如果不想看步骤的可以直接看最后面有完整的代码最近在做一个圆形的进度条,在网上看了一些例子有些地方不太理解,后来自己写了个一个分享一下先上一个最终的效果首先画一整个圆定义进度为定义总进度为定义圆的半径为至此大圆画完上面的代码需要注意的是方法的

</>复制代码

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

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

先上一个最终的效果

首先画一整个圆

</>复制代码

  1. const cvsWitdh = 220
  2. const cvsHeight = 220
  3. const progess = 50 // 定义进度为50
  4. const maxPro = 100 // 定义总进度为100
  5. const r = 100 // 定义圆的半径为100
  6. this.cvs.width = cvsWitdh
  7. this.cvs.height = cvsHeight
  8. const ctx = this.cvs.getContext("2d")
  9. ctx.lineWidth = 10
  10. ctx.strokeStyle = "#15496B"
  11. ctx.arc(r + 10, r + 10, r, 0, 2 * Math.PI)
  12. ctx.stroke() // 至此大圆画完

</>复制代码

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

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

</>复制代码

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

</>复制代码

  1. 上面的代码中 ctx.lineCap = "round" 这个是设置最终绘制的线是带圆角的
起点的弧度计算方式

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

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

终点的弧度计算方式

</>复制代码

  1. const rate = progress / maxPro
  2. 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 时画整圆

当前效果

动画实现

</>复制代码

  1. let currentProgress = 1
  2. const timer = setInterval(() => {
  3. if (currentProgress >= progress) {
  4. currentProgress = progress
  5. clearInterval(timer)
  6. }
  7. ctx.beginPath()
  8. ctx.lineCap = "round"
  9. // 下面是渐变的代码不需要的可以换成纯色
  10. let grd = ctx.createLinearGradient(0, 0, 220, 220)
  11. grd.addColorStop(0, "red")
  12. grd.addColorStop(1, "blue")
  13. ctx.strokeStyle = grd
  14. const startRadian = currentProgress >= maxPro ? 0 : Math.PI * 1.5
  15. const rate = currentProgress / maxPro
  16. const endRadian = currentProgress >= maxPro ? 2 * Math.PI : 2 * Math.PI * rate - Math.PI / 2
  17. ctx.arc(r + 10, r + 10, r, startRadian, endRadian)
  18. ctx.stroke()
  19. currentProgress++
  20. }, 10)

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

完整的代码

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

</>复制代码

  1. import React from "react"
  2. export default class Test extends React.Component {
  3. componentDidMount () {
  4. this.renderProgress(30)
  5. }
  6. renderProgress (progress) {
  7. const cvsWitdh = 220
  8. const cvsHeight = 220
  9. const maxPro = 100 // 定义总进度为100
  10. const r = 100 // 定义圆的半径为100
  11. this.cvs.width = cvsWitdh
  12. this.cvs.height = cvsHeight
  13. const ctx = this.cvs.getContext("2d")
  14. ctx.lineWidth = 10
  15. ctx.strokeStyle = "#15496B"
  16. ctx.arc(r + 10, r + 10, r, 0, 2 * Math.PI) // 2 * Math.PI === 360 度 最后一个参数代表的是圆的弧度
  17. ctx.stroke() // 至此大圆画完
  18. if (progress === 0) {
  19. return
  20. }
  21. let currentProgress = 1
  22. const timer = setInterval(() => {
  23. if (currentProgress >= progress) {
  24. currentProgress = progress
  25. clearInterval(timer)
  26. }
  27. ctx.beginPath()
  28. ctx.lineCap = "round"
  29. // 下面是渐变的代码不需要的可以换成纯色
  30. let grd = ctx.createLinearGradient(0, 0, 220, 220)
  31. grd.addColorStop(0, "red")
  32. grd.addColorStop(1, "blue")
  33. ctx.strokeStyle = grd
  34. const startRadian = currentProgress >= maxPro ? 0 : Math.PI * 1.5
  35. const rate = currentProgress / maxPro
  36. const endRadian = currentProgress >= maxPro ? 2 * Math.PI : 2 * Math.PI * rate - Math.PI / 2
  37. ctx.arc(r + 10, r + 10, r, startRadian, endRadian)
  38. ctx.stroke()
  39. currentProgress++
  40. }, 10)
  41. }
  42. render () {
  43. return (


  44. {
  45. this.cvs = ref
  46. }}
  47. />


  48. this.renderProgress(60)
  49. }}>重新loadprogress
  50. )
  51. }
  52. }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104702.html

相关文章

  • View之Canvas,Paint,Matrix,RectF等介绍

    摘要:将当前状态保存在堆栈,之后可以调用的平移旋转错切剪裁等操作。恢复为之前堆栈保存的状态,防止后对执行的操作对后续的绘制有影响。 目录介绍 1.Paint画笔介绍 1.1 图形绘制 1.2 文本绘制 2.Canvas画布介绍 2.1 设置属性 2.2 画图【重点】 2.3 Canvas对象的获取方式 2.4 Canvas的作用 2.5 Canvas绘制圆和椭圆 2.6 Can...

    khs1994 评论0 收藏0
  • 射鸡狮说圆形进度不是我要的效果

    摘要:一个没什么特别的日子,你接到了一个没什么特别的设计图,准备写个没什么特别的活动页,然后,看到了一个效果唔,射鸡狮啊,你这个圆是不是没画好啊,缺了个角。唔,那个是不是可以画画作为一个熟练操作和的前端工程师,那就去看看有没有提供什么让我们的吧。 一个没什么特别的日子,你接到了一个没什么特别的设计图,准备写个没什么特别的活动页,然后,看到了一个效果:showImg(https://segme...

    gyl_coder 评论0 收藏0
  • 射鸡狮说圆形进度不是我要的效果

    摘要:一个没什么特别的日子,你接到了一个没什么特别的设计图,准备写个没什么特别的活动页,然后,看到了一个效果唔,射鸡狮啊,你这个圆是不是没画好啊,缺了个角。唔,那个是不是可以画画作为一个熟练操作和的前端工程师,那就去看看有没有提供什么让我们的吧。 一个没什么特别的日子,你接到了一个没什么特别的设计图,准备写个没什么特别的活动页,然后,看到了一个效果:showImg(https://segme...

    defcon 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<