微信小程序canvas实现抽奖动画

本来想用setdata做抽奖动画的,但是存在合并更新以及性能问题,遂采用canvas的形式。

参考了一篇blog,然后加了些抽奖逻辑的改动

html 复制代码
<!--components/names/names.wxml-->
<view class="component-names">
  <canvas type="2d" id="myCanvas" style="width: 200px;height: 200px;"></canvas>
</view>
javascript 复制代码
import { getRandomInt } from "../../utils/util";

// components/names/names.ts
Component({
  lifetimes: {
    attached() {
      this.createSelectorQuery().select("#myCanvas").fields({
        node: true,
        size: true
      }).exec(res => this.init(res));
    },
  },
  /**
   * 组件的属性列表
   */
  properties: {
    names: {
      type: Array,
      value: ['小红', '大明', '阿花']
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {
    init(res) {
      // console.log('init', res)
      const width = res[0].width
      const height = res[0].height
      // 设置画布宽高
      const canvas = res[0].node
      const ctx = canvas.getContext('2d')
      canvas.width = width
      canvas.height = height
      /** 半径 */
      let rArr = [];
      /** 透明度 */
      let alpha = [];

      const renderLoop = () => {
        /** 最小半径 */
        const circleStartR = width / 2 - 40;
        /** 最大半径 */
        const circleEndR = width / 2 - 8;
        /** 动画时间 */
        let animationTime = 300;
        /** 每次增大的宽度 */
        let speed = (circleEndR - circleStartR) / animationTime;

        rArr = rArr.map(item => item + speed);
        alpha = alpha.map(item => item + 1 / animationTime);
        // 如果数组为空|| 最小圆半径-最小半径>圆间隔
        if (!rArr[0] || rArr[0] - circleStartR > 10) {
          rArr.unshift(circleStartR);
          alpha.unshift(0);
        }

        // 如果最大圆半径>=最大半径
        if (rArr[rArr.length - 1] >= circleEndR) {
          rArr.pop();
        }

        this.render(width, ctx, rArr, alpha)
        canvas.requestAnimationFrame(renderLoop)
      }
      canvas.requestAnimationFrame(renderLoop)
    },
    renderName(width, ctx) {
      const center = width / 2;
      ctx.clearRect(center - 50, center - 50, center, center)
      let name = this.properties.names[getRandomInt(0, this.properties.names.length - 1)];
      let w = ctx.measureText(name).width;
      ctx.fillText(name, center - w / 2, center + 10)
      ctx.font = '30px bold'
    },
    render(width, ctx, rArr, alpha) {
      ctx.clearRect(0, 0, width, width);
      const center = width / 2;
      this.renderName(width, ctx);
      function ball(r, a) {
        // 设置渐变
        let grd = ctx.createLinearGradient(0, 0, 100, 0);
        grd.addColorStop(0, 'rgba(132, 251, 251, ' + a + ')') //渐变颜色的添加
        grd.addColorStop(0.5, 'rgba(118, 133, 254, ' + a + ')');
        grd.addColorStop(1, 'rgba(2545, 4, 255, ' + a + ')');
        ctx.beginPath();
        // 画圆
        ctx.arc(center, center, r, 0, 2 * Math.PI);
        // 描边样式设置
        ctx.strokeStyle = grd;
        ctx.closePath();
        // 描边
        ctx.stroke();
      }
      for (let i = 0; i < rArr.length; i++) {
        let r = rArr[i];
        let a = alpha[i];
        ball(r, a);
      }
    },
  }
})

参考:微信小程序canvas制作动画_微信小程序 canvas动画-CSDN博客

相关推荐
幽络源小助理8 分钟前
SpringBoot+小程序高校素拓分管理系统源码 – 幽络源免费分享
spring boot·后端·小程序
Mr -老鬼34 分钟前
移动端跨平台适配技术框架:从发展到展望
android·ios·小程序·uni-app
内存不泄露1 小时前
棋牌预约小程序系统论文
小程序
计算机徐师兄3 小时前
Java基于微信小程序的食堂线上预约点餐系统【附源码、文档说明】
java·微信小程序·食堂线上预约点餐系统小程序·食堂线上预约点餐微信小程序·java食堂线上预约点餐小程序·食堂线上预约点餐小程序·食堂线上预约点餐系统微信小程序
说私域20 小时前
短视频私域流量池的变现路径创新:基于AI智能名片链动2+1模式S2B2C商城小程序的实践研究
大数据·人工智能·小程序
毕设源码-邱学长21 小时前
【开题答辩全过程】以 基于微信小程序的松辽律所咨询系统的设计与实现为例,包含答辩的问题和答案
微信小程序·小程序
+VX:Fegn08951 天前
计算机毕业设计|基于springboot + vue物流配送中心信息化管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·小程序·课程设计
说私域1 天前
B站内容生态下的私域流量运营创新:基于AI智能名片链动2+1模式与S2B2C商城小程序的融合实践
人工智能·小程序·流量运营
计算机毕设指导61 天前
基于微信小程序的钓鱼论坛系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
qq_12498707531 天前
基于微信小程序的宠物交易平台的设计与实现(源码+论文+部署+安装)
java·spring boot·后端·微信小程序·小程序·毕业设计·计算机毕业设计