react写的一个九宫格抽奖活动

本文介绍了一个基于React的抽奖动画实现方案,通过动态更新组件状态,实现了九宫格抽奖动画效果。文章详细解释了如何设置动画次数,判断中奖条件以及动画执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看效果

在这里插入图片描述

代码如下:

父组件:

import React, { Component } from 'react'
import DeomItem from './demo_item.jsx' // 引入子组件
export default class demo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // 九宫格内容list
      list: [
        {id: 1, name: '1.2%财富券'},
        {id: 2, name: '1.0%财富券'},
        {id: 3, name: '1.4%财富券'},
        {id: 4, name: '1.1%财富券'},
        {id: 5, name: '电视'},
        {id: 6, name: '冰箱'},
        {id: 7, name: '洗衣机'},
        {id: 8, name: '手机'},
        {id: 9, name: '手机1'},
        {id: 10, name: '手机2'},
        {id: 11, name: '手机3'},
        {id: 12, name: '手机4'}
      ],
      // 被选中的格子的ID
      activedId: '',
      // 中奖ID
      prizeId: null,
      // 获得prizeId之后计算出的动画次数
      times: 0,
      // 当前动画次数
      actTimes: 0,
      // 是否正在抽奖
      isRolling: false
    }
  }
  handleBegin() {
    // this.state.isRolling为false的时候才能开始抽,不然会重复抽取,造成无法预知的后果
    if (!this.state.isRolling) {
      // 点击抽奖之后,我个人做法是将于九宫格有关的状态都还原默认
      this.setState({
        activedId: '',
        prizeId: null,
        times: 0,
        actTimes: 0,
        isRolling: true
      }, () => {
        // 状态还原之后才能开始真正的抽奖
        this.handlePlay()
      })
    }
  }
  handlePlay() {
    // 中将id,可随机,可自己设定,我这里暂且定为4
    let prize = 4
    console.log(prize)
    this.setState({
      prizeId: prize,
      activedId: 0
    })
    // 随机算出一个动画执行的最小次数,这里可以随机变更数值,按自己的需求来
    let times = this.state.list.length * Math.floor(Math.random() * 5 + 4)
    this.setState({
      times: times
    })
    // 抽奖正式开始
    this.begin = setInterval(() => {
      let num;

      if (this.state.activedId === this.state.prizeId && this.state.actTimes > this.state.times) {
        // 符合上述所有条件时才是中奖的时候,两个ID相同并且动画执行的次数大于(或等于也行)设定的最小次数
        clearInterval(this.begin)
        this.setState({
          isRolling: false
        })
        return
      }

      // 以下是动画执行时对id的判断
      if (this.state.activedId === '') {
        num = 0
        this.setState({
          activedId: num
        })
      } else {
        num = this.state.activedId
        if (num === 11) {
          num = 0
          this.setState({
            activedId: num
          })
        } else {
          num = num + 1
          this.setState({
            activedId: num
          })
        }
      }

      this.setState({
        actTimes: this.state.actTimes + 1
      })

    }, 40)
  }
  render() {
    const { list, activedId } = this.state;
    return (
      <div className="demo">
        <div className="start_button" onClick={() => this.handleBegin()}>开始</div>
        <div className="one">
          <DeomItem content={list[0]} activedId={activedId}></DeomItem>
          <DeomItem content={list[1]} activedId={activedId}></DeomItem>
          <DeomItem content={list[2]} activedId={activedId}></DeomItem>
          <DeomItem content={list[3]} activedId={activedId}></DeomItem>
        </div>
        <div className="one">
          <DeomItem content={list[11]} activedId={activedId}></DeomItem>
          <DeomItem content={list[4]} activedId={activedId}></DeomItem>
        </div>
        <div className="one">
          <DeomItem content={list[10]} activedId={activedId}></DeomItem>
          <DeomItem content={list[5]} activedId={activedId}></DeomItem>
        </div>
        <div className="one">
          <DeomItem content={list[9]} activedId={activedId}></DeomItem>
          <DeomItem content={list[8]} activedId={activedId}></DeomItem>
          <DeomItem content={list[7]} activedId={activedId}></DeomItem>
          <DeomItem content={list[6]} activedId={activedId}></DeomItem>
        </div>
      </div>
    );
  }
}

子组件:

import React, { Component } from 'react'
export default class demoItem extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    const { content, activedId } = this.props;
    return (
      <div className={activedId === content.id ? 'row_item row_item-active' : 'row_item'} id={`row_item_${content}`}>
        {content.name}
      </div>
    );
  }
}

css样式:
我这里用的是scss

@function rem($px){
  @return $px * 36 / 7200 + rem;
}
.demo {
  height: rem(655);
  margin: rem(20);
  border: 1px solid #333;
  background: #fff;
  position: relative;
  .start_button {
    display: flex;
    justify-content: center;
    position: absolute;
    left: calc(50% - 40px);
    top: calc(50% - 20px);
    width: rem(150);
    height: rem(60);
    line-height: rem(60);
    text-align: center;
    background: aliceblue;
  }
  .one {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    .row_item {
      width: rem(150);
      height: rem(150);
      line-height: rem(150);
      text-align: center;
      background: #f0f0f0;
    }
    .row_item-active {
     background: aquamarine;
     animation: blink 1s 3;
    }
    @keyframes blink{
      to {
        color: transparent;
      }
    }
  }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值