如何vue制作一个抽奖页面

直接上源码

<template>
    <div class="wheel-container">
      <canvas id="wheelCanvas" width="500" height="500"></canvas>
      <button @click="spinWheel">抽奖</button>
    </div>
  </template>
  
  <script lang="ts" setup>
  import { ref, onMounted } from 'vue';
  
  interface Segment {
    label: string; //内容
    weight: number; //占比
    color: string; // 颜色
  }
  
  // 自定义每个segment的占比和颜色
  const segments: Segment[] = [
    { label: '奖品1', weight: 1, color: 'red' },
    { label: '奖品2', weight: 2, color: 'blue' },
    { label: '奖品3', weight: 3, color: 'green' },
    { label: '奖品4', weight: 4, color: 'yellow' },
    { label: '奖品5', weight: 5, color: 'pink' },
    { label: '奖品6', weight: 1, color: 'cyan' }
  ];
  
  const totalWeight = segments.reduce((sum, segment) => sum + segment.weight, 0);
  const rotation = ref(0);
  const isSpinning = ref(false);
  
  const drawWheel = () => {
    const canvas = document.getElementById('wheelCanvas') as HTMLCanvasElement;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;
  
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const radius = Math.min(centerX, centerY);
    let currentAngle = rotation.value;
  
    segments.forEach((segment, index) => {
      const segmentAngle = (segment.weight / totalWeight) * 360;
      const startAngle = (currentAngle * Math.PI) / 180;
      const endAngle = ((currentAngle + segmentAngle) * Math.PI) / 180;
  
      ctx.beginPath();
      ctx.moveTo(centerX, centerY);
      ctx.arc(centerX, centerY, radius, startAngle, endAngle);
      ctx.closePath();
  
      ctx.fillStyle = segment.color; // 使用每个 segment 定义的颜色
      ctx.fill();
      ctx.stroke();
  
      ctx.save();
      ctx.translate(centerX, centerY);
      ctx.rotate((startAngle + endAngle) / 2);
      ctx.textAlign = 'center';
      ctx.fillStyle = '#000';
      ctx.fillText(segment.label, radius / 1.5, 0);
      ctx.restore();
  
      currentAngle += segmentAngle;
    });
  
    // Draw center arrow
    ctx.beginPath();
    ctx.moveTo(centerX - 10, centerY - radius);
    ctx.lineTo(centerX + 10, centerY - radius);
    ctx.lineTo(centerX, centerY - radius + 20);
    ctx.fillStyle = '#FF0000';
    ctx.fill();
  };
  
  const spinWheel = () => {
    if (isSpinning.value) return;
  
    isSpinning.value = true;
    //控制圈数 至少3圈
    const randomRotation = Math.floor(Math.random() * 360) + 360 * 3;
    //控制旋转速度
    const duration = 3000;
  
    const start = performance.now();
  
    const animate = (time: number) => {
      const elapsed = time - start;
      if (elapsed < duration) {
        rotation.value = (randomRotation * (elapsed / duration)) % 360;
        drawWheel();
        requestAnimationFrame(animate);
      } else {
        rotation.value = randomRotation % 360;
        drawWheel();
        isSpinning.value = false;
      }
    };
  
    requestAnimationFrame(animate);
  };
  
  onMounted(() => {
    drawWheel();
  });
  </script>
  
  <style scoped>
  .wheel-container {
    text-align: center;
    margin-top: 50px;
  }
  
  canvas {
    border: 2px solid #000;
    border-radius: 50%;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  }
  
  button {
    margin-top: 20px;
    padding: 10px 20px;
    font-size: 16px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
  }
  
  button:hover {
    background-color: #0056b3;
  }
  </style>
  

代码支持选项占比/颜色控制,旋转圈数控制,旋转速度控制
一次复制,到处运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

azoon.top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值