微信小程序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博客

相关推荐
程序鉴定师18 小时前
如何选择合适的深圳小程序开发公司?
大数据·小程序
阿豪啊20 小时前
微信小程序订阅消息实战:从模板配置到发送全流程
微信小程序
云起SAAS1 天前
私域直播系统UniApp源码 多商户商城+直播带货 微信小程序+H5+安卓iOS
android·微信小程序·uni-app·私域直播系统
代码不加糖1 天前
从零手写简易 Taro:20 行 JSX 如何变成小程序?(硬核实战)
小程序·taro
云云只是个程序马喽2 天前
AI漫剧创作系统开发定制指南
人工智能·小程序·php
斯班奇的好朋友阿法法2 天前
鸿蒙 vs iOS vs 微信小程序:开发平台全面对比
ios·微信小程序·harmonyos
cosinmz3 天前
图片太多太乱怎么整理?分享一个我最近常用的图片转 PDF方法
经验分享·小程序·pdf
科技互联.3 天前
2026年小程序定制市场:个性化需求激增,技术深度成竞争关键
人工智能·小程序
小羊Yveesss3 天前
2026年小程序商城的现状和发展趋势
小程序
Greg_Zhong4 天前
微信小程序如何关闭:当前渲染模式为webview?
微信小程序·微信小程序渲染引擎·渲染引擎需搭配更高基础库