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

相关推荐
00后程序员张1 小时前
iOS软件性能监控实战指南 开发到上线的完整流程解析
android·ios·小程序·https·uni-app·iphone·webview
weixin_lynhgworld4 小时前
剧本杀小程序系统开发:构建数字化剧本杀生态圈
大数据·小程序·剧本杀
落雪小轩韩16 小时前
微信小程序性能优化与内存管理
微信小程序
徐礼昭|商派软件市场负责人1 天前
从“多、老、旧”到“4i焕新”:品牌官方商城(小程序/官网/APP···)的范式跃迁与增长再想象
小程序·商城系统·零售
胡西风_foxww2 天前
微信小程序转Vue2组件智能提示词
微信小程序·小程序·提示词·智能体·vue2组件
七七软件开发2 天前
一对一交友小程序 / APP 系统架构分析
java·python·小程序·系统架构·php
2501_916007472 天前
iPhone查看App日志和系统崩溃日志的完整实用指南
android·ios·小程序·https·uni-app·iphone·webview
说私域2 天前
基于开源链动2+1模式AI智能名片S2B2C商城小程序的私域流量拉新策略研究
人工智能·小程序·开源
2501_915918412 天前
iOS 抓不到包怎么办?全流程排查思路与替代引导
android·ios·小程序·https·uni-app·iphone·webview
七七软件开发2 天前
团购商城 app 系统架构分析
java·python·小程序·eclipse·系统架构·php