uniapp+vue2 大转盘如何实现

在uniapp+vue2项目中,想实现一个大转盘抽奖功能,但不太清楚具体怎么操作。请问如何用canvas或CSS3实现转盘的旋转动画?需要哪些关键步骤?怎么控制转盘停止在指定奖品位置?求一个完整的实现思路或示例代码。

2 回复

使用uni-app + Vue2实现大转盘:

  1. 使用canvas绘制转盘和指针
  2. 定义奖品数组,计算每个奖品角度
  3. 使用CSS3动画实现旋转效果
  4. 通过Math.random()随机生成中奖结果
  5. 监听touchstart/touchend事件控制开始/停止
  6. 使用uni.createAnimation()实现平滑停止动画

核心代码:

rotate() {
  this.animation.rotate(3600).step()
  this.animationData = this.animation.export()
}

在 UniApp + Vue2 中实现大转盘功能,可以通过以下步骤完成:

1. 页面布局

使用 view 和 CSS 绘制转盘和指针,奖品区域用圆形分割。

<template>
  <view class="wheel-container">
    <!-- 转盘 -->
    <view class="wheel" :style="wheelStyle" @click="startRotate">
      <!-- 奖品区块 -->
      <view v-for="(item, index) in prizes" :key="index" class="prize-item" :style="getItemStyle(index)">
        {{ item.name }}
      </view>
    </view>
    <!-- 指针 -->
    <view class="pointer"></view>
  </view>
</template>

2. 数据与样式

定义奖品数据和转盘样式,计算每个奖品区块的旋转角度。

export default {
  data() {
    return {
      prizes: [
        { name: '奖品1' },
        { name: '奖品2' },
        { name: '奖品3' },
        { name: '奖品4' },
        { name: '奖品5' },
        { name: '奖品6' }
      ],
      rotating: false,
      resultIndex: 0 // 指定停止的奖品索引
    }
  },
  computed: {
    wheelStyle() {
      return {
        transform: `rotate(${this.rotateDeg}deg)`,
        transition: `transform ${this.duration}s ease-out`
      }
    }
  },
  methods: {
    getItemStyle(index) {
      const angle = 360 / this.prizes.length;
      return {
        transform: `rotate(${angle * index}deg)`,
        'transform-origin': 'center center'
      }
    }
  }
}

3. 旋转动画

通过改变 rotateDeg 触发 CSS 过渡动画,计算停止角度。

methods: {
  startRotate() {
    if (this.rotating) return;
    this.rotating = true;
    
    // 随机选择奖品(或根据后端结果)
    this.resultIndex = Math.floor(Math.random() * this.prizes.length);
    
    // 计算旋转角度(多转几圈增加效果)
    const anglePerItem = 360 / this.prizes.length;
    const stopAngle = 3600 - (anglePerItem * this.resultIndex); // 基础圈数 + 停止位置
    
    this.rotateDeg = stopAngle;
    this.duration = 5; // 动画持续时间
    
    // 动画结束后重置状态
    setTimeout(() => {
      this.rotating = false;
      uni.showToast({
        title: `恭喜获得:${this.prizes[this.resultIndex].name}`,
        icon: 'none'
      });
    }, this.duration * 1000);
  }
}

4. CSS 样式

.wheel-container {
  position: relative;
  width: 300px;
  height: 300px;
  margin: 50px auto;
}

.wheel {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: conic-gradient(
    red, yellow, green, blue, purple, orange
  );
  position: relative;
  overflow: hidden;
}

.prize-item {
  position: absolute;
  width: 50%;
  height: 50%;
  left: 50%;
  top: 0;
  transform-origin: left bottom;
  text-align: center;
  line-height: 150px;
}

.pointer {
  position: absolute;
  top: -20px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-top: 20px solid #000;
}

关键点说明:

  • 转盘绘制:使用 conic-gradient 背景或绝对定位元素实现扇形分割
  • 动画控制:通过改变 transform: rotate() 并设置 transition 实现平滑旋转
  • 停止位置:通过计算目标奖品对应的角度确定停止位置
  • 交互限制:旋转过程中禁用点击防止重复触发

实际项目中需要根据奖品数量调整角度计算,并可以接入后端 API 获取抽奖结果。

回到顶部