|
@@ -1,266 +0,0 @@
|
|
|
-"use client";
|
|
|
-
|
|
|
-import React, { useEffect, useRef } from 'react';
|
|
|
-
|
|
|
-
|
|
|
-const LotteryWheel = () => {
|
|
|
-
|
|
|
- const canvasRef = useRef<any>(null);
|
|
|
-
|
|
|
- const ctxRef = useRef<any>(null);
|
|
|
-
|
|
|
- const centerX = 153; // 画布宽度的一半
|
|
|
-
|
|
|
- const centerY = 153; // 画布高度的一半
|
|
|
-
|
|
|
- const radius = 130; // 大转盘的半径
|
|
|
-
|
|
|
- const segments = 8; // 大转盘的份数
|
|
|
-
|
|
|
- const colors = [
|
|
|
-
|
|
|
- '#FF5733', '#33FF57', '#3357FF', '#F3FF33',
|
|
|
-
|
|
|
- '#FF33A1', '#33FFF1', '#FF8A33', '#A133FF'
|
|
|
-
|
|
|
- ];
|
|
|
-
|
|
|
- let isSpinning = false;
|
|
|
-
|
|
|
- let startAngle = 0;
|
|
|
-
|
|
|
- let spinTime = 0;
|
|
|
-
|
|
|
- let spinTimeTotal = 0;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- const drawWheel = () => {
|
|
|
-
|
|
|
- const canvas:any = canvasRef.current;
|
|
|
-
|
|
|
- const ctx = canvas.getContext('2d');
|
|
|
-
|
|
|
- ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // 画外圈
|
|
|
-
|
|
|
- ctx.beginPath();
|
|
|
-
|
|
|
- ctx.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
|
|
|
-
|
|
|
- ctx.lineWidth = 10;
|
|
|
-
|
|
|
- ctx.strokeStyle = '#000';
|
|
|
-
|
|
|
- ctx.stroke();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // 画每一份
|
|
|
-
|
|
|
- for (let i = 0; i < segments; i++) {
|
|
|
-
|
|
|
- const angle = (Math.PI * 2) / segments * i;
|
|
|
-
|
|
|
- const x1 = centerX + radius * 0.9 * Math.cos(angle - Math.PI / 2);
|
|
|
-
|
|
|
- const y1 = centerY + radius * 0.9 * Math.sin(angle - Math.PI / 2);
|
|
|
-
|
|
|
- const x2 = centerX + radius * Math.cos(angle - Math.PI / 2);
|
|
|
-
|
|
|
- const y2 = centerY + radius * Math.sin(angle - Math.PI / 2);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- ctx.beginPath();
|
|
|
-
|
|
|
- ctx.moveTo(x1, y1);
|
|
|
-
|
|
|
- ctx.lineTo(x2, y2);
|
|
|
-
|
|
|
- ctx.lineWidth = 10;
|
|
|
-
|
|
|
- ctx.strokeStyle = colors[i];
|
|
|
-
|
|
|
- ctx.stroke();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // 填充颜色
|
|
|
-
|
|
|
- ctx.beginPath();
|
|
|
-
|
|
|
- ctx.moveTo(centerX, centerY);
|
|
|
-
|
|
|
- ctx.arc(centerX, centerY, radius * 0.9, angle - Math.PI / 2, angle + Math.PI / (2 * segments) - Math.PI / 2, false);
|
|
|
-
|
|
|
- ctx.lineTo(centerX, centerY);
|
|
|
-
|
|
|
- ctx.fillStyle = colors[i];
|
|
|
-
|
|
|
- ctx.fill();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- const spinWheel = () => {
|
|
|
-
|
|
|
- isSpinning = true;
|
|
|
-
|
|
|
- startAngle = Math.random() * Math.PI * 2;
|
|
|
-
|
|
|
- spinTime = 0;
|
|
|
-
|
|
|
- spinTimeTotal = Math.random() * 3 + 3; // 3到6秒的旋转时间
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- const spinTick = () => {
|
|
|
-
|
|
|
- if (!isSpinning) return;
|
|
|
-
|
|
|
- spinTime += 30;
|
|
|
-
|
|
|
- const spinDegree = spinTime / spinTimeTotal * Math.PI * 2;
|
|
|
-
|
|
|
- const ctx = ctxRef.current;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
|
|
|
-
|
|
|
- drawWheel();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // 旋转画布
|
|
|
-
|
|
|
- ctx.save();
|
|
|
-
|
|
|
- ctx.translate(centerX, centerY);
|
|
|
-
|
|
|
- ctx.rotate(spinDegree + startAngle);
|
|
|
-
|
|
|
- // 重新绘制每一份到中心线位置
|
|
|
-
|
|
|
- for (let i = 0; i < segments; i++) {
|
|
|
-
|
|
|
- const angle = (Math.PI * 2) / segments * i;
|
|
|
-
|
|
|
- const x = radius * Math.cos(angle - Math.PI / 2);
|
|
|
-
|
|
|
- const y = radius * Math.sin(angle - Math.PI / 2);
|
|
|
-
|
|
|
- ctx.beginPath();
|
|
|
-
|
|
|
- ctx.moveTo(0, 0);
|
|
|
-
|
|
|
- ctx.lineTo(x, y);
|
|
|
-
|
|
|
- ctx.lineWidth = 10;
|
|
|
-
|
|
|
- ctx.strokeStyle = colors[i];
|
|
|
-
|
|
|
- ctx.stroke();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- ctx.restore();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (spinTime < spinTimeTotal) {
|
|
|
-
|
|
|
- requestAnimationFrame(spinTick);
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- stopWheel();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- spinTick();
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- const stopWheel = () => {
|
|
|
-
|
|
|
- isSpinning = false;
|
|
|
-
|
|
|
- const degrees = startAngle + (spinTime / spinTimeTotal) * Math.PI * 2;
|
|
|
-
|
|
|
- const index = Math.floor((degrees % (Math.PI * 2)) / (Math.PI * 2 / segments));
|
|
|
-
|
|
|
- alert(`你抽中了第 ${index + 1} 份!`);
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- const handleClick = (e:any) => {
|
|
|
-
|
|
|
- const rect = canvasRef.current.getBoundingClientRect();
|
|
|
-
|
|
|
- const x = e.clientX - rect.left;
|
|
|
-
|
|
|
- const y = e.clientY - rect.top;
|
|
|
-
|
|
|
- const distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- if (distance < radius * 0.75) { // 0.75倍半径内视为点击中间区域
|
|
|
-
|
|
|
- spinWheel();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
-
|
|
|
- const canvas:any = canvasRef?.current;
|
|
|
-
|
|
|
- const ctx = canvas.getContext('2d');
|
|
|
-
|
|
|
- ctxRef.current = ctx;
|
|
|
-
|
|
|
- drawWheel();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- canvas.addEventListener('click', handleClick);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- return () => {
|
|
|
-
|
|
|
- canvas.removeEventListener('click', handleClick);
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- }, []);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- return <canvas ref={canvasRef} width={306} height={306} style={{ cursor: 'pointer' }} />;
|
|
|
-
|
|
|
-};
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- export default LotteryWheel;
|