wepy小程序canvas实现渐变圆环倒计时

工作中遇到需要实现圆环式渐变颜色的进度条倒计时,这篇文章记录一下,方便日后查看。

本文内容只是实现了简单的5S 10S 20S等(符合100的因数) 倒计时。
1.效果图:

 2.代码

<template>
  <view class="progress-box">
    <!-- 旧的 -->
    <canvas style="width: 370px; height: 370px; border: 2px solid red;" canvas-id="firstCanvas">

    </canvas>
    <button bindtap="timeDown(5)">5s倒计时</button>
    <button bindtap="timeDown(25)">25s倒计时</button>
    <button bindtap="timeDown(100)">100s倒计时</button>
  </view>
</template>

<script>
import wepy from 'wepy';

export default class circleProgress extends wepy.page {
  config = {
    navigationBarTitleText: 'canvas环形渐变进度条',
    navigationBarBackgroundColor: '#F9F9F9',
  };
  data = {
    colorArr: [],
    precent: 100,
    startColor: '#FFA309',
    endColor: '#FF5E0B',
    num: 0, // 当前进度
    context: null,
    id: null,
    allTime: 5,
    nums: []
  };
  methods = {
    timeDown(e) {
      this.allTime = Number(e)
      this.num = 0
      this.nums = []
      this.calNums()
      this.calInterTime()
      this.draw()
    }
  }
  calNums() {
    let singleNum = this.precent / this.allTime
    for(let i = 0; i <= this.allTime; i++) {
      this.nums.push(singleNum * i)
    }
    // console.log('this.nums', this.nums)
  }
  calInterTime() {
    this.inter = this.allTime * 1000 / this.precent
    // console.log('this.inter', this.inter)
  }
  getColorArr() {
    let startRgb = this.hexToRgb(this.startColor)
    let endRgb = this.hexToRgb(this.endColor)

    let stepR = (endRgb[0] - startRgb[0]) / this.precent
    let stepG = (endRgb[1] - startRgb[1]) / this.precent
    let stepB = (endRgb[2] - startRgb[2]) / this.precent

    for (let i = 0; i <= this.precent; i++) {
        let hex = this.rgbToHex(startRgb[0] + stepR * i, startRgb[1] + stepG * i, startRgb[2] + stepB * i)
        hex = hex.length == 4 ? ('00' + hex) : hex.length == 5 ? ('0' + hex) : hex
        this.colorArr.push('#' + hex)
    }
    // console.log('this.colorArr', this.colorArr)
  }
  hexToRgb(hex) {
      if (hex.length == 4)
          return [parseInt('0x' + hex.slice(1, 2).repeat(2)), parseInt('0x' + hex.slice(2, 3).repeat(2)), parseInt('0x' + hex.slice(3, 4).repeat(2))]
      else if (hex.length == 7)
          return [parseInt('0x' + hex.slice(1, 3)), parseInt('0x' + hex.slice(3, 5)), parseInt('0x' + hex.slice(5, 7))]
      else
          alert('颜色错误')
  }

  rgbToHex(r, g, b) {
      return ((r << 16) | (g << 8) | b).toString(16)
  }

  onLoad(options) {
    this.init()
  }
  onShow() {}
  init() {
    this.context = wx.createCanvasContext('firstCanvas')
    this.getColorArr()
  }
  draw() {
    this.context.clearRect(0, 0, 370, 370)
    this.drawCircle()
    let index = -1
    this.id = setInterval(() => {
      if(this.num <= this.precent) {
        index = this.nums.indexOf(this.num)
        if(index > -1) {
          this.context.clearRect(105, 105, 90, 90)
          this.drawText(this.nums.length - index - 1)
        }
        this.drawProgress(this.num, this.precent)
        this.num++
        console.log('this.num', this.num)
      } else {
        clearInterval(this.id)
      }
    }, this.inter);
  }
  // 画字
  drawText(currentTime) {
    this.context.save();
    this.context.fillStyle = '#3396c7'
    this.context.font = '40px Helvetica'
    this.context.textAlign = 'center';
    this.context.fillText(currentTime + 'S', 150, 160)
    this.context.restore()
  }
  // 画进度条
  drawProgress(num, precent) {
    this.context.setLineWidth(50)
    this.context.setStrokeStyle(this.colorArr[num])
    this.context.setLineCap('round')
    this.context.arc(150, 150, 100, - Math.PI / 2 + (num - 1) * 2 * Math.PI / precent, - Math.PI / 2 + num *  2 * Math.PI / precent)
    this.context.stroke()
    this.context.draw(true)
  }
  // 画轨道
  drawCircle() {
    this.context.arc(150, 150, 100, 0, 2 * Math.PI)
    this.context.setLineWidth(50)
    this.context.setStrokeStyle('yellow')
    this.context.setLineCap('round')
    this.context.stroke()
    this.context.draw()
  }
  watch = {

  }
}
</script>

<style lang="less">

</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用CanvasContext中的`arc()`和`fillText()`方法来实现倒计时的效果。具体实现步骤如下: 1. 首先获取到CanvasContext的实例: ```javascript const ctx = wx.createCanvasContext('myCanvas'); ``` 2. 然后通过`arc()`方法画出一个圆形的进度条: ```javascript ctx.beginPath(); ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise); ctx.stroke(); ``` 其中,`x`和`y`是圆心的坐标,`radius`是圆的半径,`startAngle`和`endAngle`是圆弧的起始角度和结束角度,`anticlockwise`表示是否按逆时针方向绘制。 3. 接着,使用`fillText()`方法在圆形中心位置显示倒计时的数字: ```javascript ctx.font = 'bold 24px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(time, x, y); ``` 其中,`font`设置字体样式,`textAlign`设置文字水平居中,`textBaseline`设置文字垂直居中,`fillText()`方法的第一个参数是要显示的文本,第二个参数是文本的x轴坐标,第三个参数是文本的y轴坐标。 4. 最后,通过定时器来更新倒计时的时间和进度条的显示,实现倒计时效果。 ```javascript setInterval(() => { //更新倒计时时间 time--; //重新绘制圆形进度条和倒计时数字 drawProgress(time); }, 1000); ``` 完整的实现代码示例: ```javascript const ctx = wx.createCanvasContext('myCanvas'); const x = 50; //圆心x轴坐标 const y = 50; //圆心y轴坐标 const radius = 40; //圆的半径 let time = 60; //倒计时时间 function drawProgress(time) { //清空画布 ctx.clearRect(0, 0, 100, 100); //绘制底部圆形 ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI); ctx.strokeStyle = '#ddd'; ctx.stroke(); //绘制进度条 const endAngle = (2 * Math.PI) * (60 - time) / 60 - 0.5 * Math.PI; ctx.beginPath(); ctx.arc(x, y, radius, -0.5 * Math.PI, endAngle); ctx.strokeStyle = '#f00'; ctx.stroke(); //绘制倒计时数字 ctx.font = 'bold 24px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(time, x, y); } setInterval(() => { time--; drawProgress(time); }, 1000); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值