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

相关推荐
2501_915918417 小时前
Fiddler中文版全面评测:功能亮点、使用场景与中文网资源整合指南
android·ios·小程序·https·uni-app·iphone·webview
说私域9 小时前
从品牌附庸到自我表达:定制开发开源AI智能名片S2B2C商城小程序赋能下的营销变革
人工智能·小程序
難釋懷9 小时前
第一个小程序
小程序
春哥的研究所9 小时前
可视化DIY小程序工具!开源拖拽式源码系统,自由搭建,完整的源代码包分享
小程序·开源·开源拖拽式源码系统·开源拖拽式源码·开源拖拽式系统
weixin_lynhgworld9 小时前
盲盒一番赏小程序技术实现方案:高并发与防作弊的平衡之道
小程序
今日热点10 小时前
小程序主体变更全攻略:流程、资料与异常处理方案
经验分享·微信·小程序·企业微信·微信公众平台·微信开放平台
鸭鸭梨吖14 小时前
微信小程序---下拉框
微信小程序·小程序
CRMEB定制开发15 小时前
CRMEB Pro版前端环境配置指南
前端·微信小程序·uni-app·商城源码·微信商城·crmeb
mon_star°18 小时前
搭建一款结合传统黄历功能的日历小程序
微信·微信小程序·小程序·微信公众平台
The_era_achievs_hero18 小时前
微信小程序91~100
微信小程序·小程序