直接上源码
<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>
代码支持选项占比/颜色控制,旋转圈数控制,旋转速度控制
一次复制,到处运行