You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS转盘游戏开发:如何捕获指针停止处的滑块内容

How to Capture the Segment Under the Pointer When Your React Wheel Spinner Stops

Hey there! Let's break down how to grab the exact segment your pointer lands on when the wheel stops spinning. I've tackled this exact problem before, so here's a practical, step-by-step solution tailored to your React setup.

Core Logic Overview

The key idea is to calculate which segment aligns with your pointer once the wheel finishes rotating. Here's the breakdown:

  • Calculate the angle each segment occupies (360° divided by the total number of segments).
  • Track the final rotation angle of the wheel once it stops.
  • Adjust that angle to account for your pointer's position, then map it to the corresponding segment.

Step-by-Step Implementation

1. Set Up Your State Variables

First, make sure you're tracking the wheel's rotation, spin state, and the winning segment:

import { useState } from 'react';

function WheelSpinner() {
  // Customize this array to match your game's segments
  const [segments] = useState(["Free Spin", "50 Points", "Lose Turn", "100 Points", "20 Points"]);
  const [rotation, setRotation] = useState(0);
  const [isSpinning, setIsSpinning] = useState(false);
  const [winningSegment, setWinningSegment] = useState(null);

  // Rest of your component code...
}

2. Calculate the Winning Segment on Stop

Create a function that runs after the wheel's rotation animation finishes to determine the winning segment. We'll use modulo arithmetic to ignore full rotations, then adjust for the pointer's position (assuming it's at the top/12 o'clock spot):

const determineWinningSegment = () => {
  const totalSegments = segments.length;
  const segmentAngle = 360 / totalSegments;

  // Get the final rotation angle (mod 360 removes full spins from the calculation)
  const finalRotation = rotation % 360;

  // Adjust angle to account for a top-positioned pointer (for clockwise spins)
  // Tweak this if your pointer is in a different spot (e.g., right side = 90° offset)
  const adjustedAngle = (360 - finalRotation) % 360;

  // Calculate which segment the pointer is hovering over
  const winningIndex = Math.floor(adjustedAngle / segmentAngle);
  const winner = segments[winningIndex];

  setWinningSegment(winner);
  alert(`You won: ${winner}!`); // Replace with your game's reward logic
};

3. Trigger Calculation When Animation Ends

Run the calculation only after the wheel's spin animation completes. If you're using CSS transitions, listen for the transitionend event on your wheel element:

return (
  <div className="game-container">
    {/* Fixed pointer over the wheel */}
    <div className="pointer"></div>

    {/* Wheel Element */}
    <div
      className={`wheel ${isSpinning ? 'spinning' : ''}`}
      style={{ transform: `rotate(${rotation}deg)` }}
      onTransitionEnd={isSpinning ? determineWinningSegment : undefined}
    >
      {/* Render each segment */}
      {segments.map((segment, index) => (
        <div
          key={index}
          className="segment"
          style={{ transform: `rotate(${index * segmentAngle}deg)` }}
        >
          {segment}
        </div>
      ))}
    </div>

    {/* Spin Button */}
    <button onClick={() => {
      setIsSpinning(true);
      // Generate a random rotation (3-5 full spins + random final angle)
      const randomRotation = Math.floor(Math.random() * 1800) + 1080;
      setRotation(prev => prev + randomRotation);
    }} disabled={isSpinning}>
      Spin the Wheel!
    </button>

    {winningSegment && <p className="winner-text">Last Win: {winningSegment}</p>}
  </div>
);

4. Add CSS for Smooth Animation

Make sure your CSS handles the rotation transition smoothly and styles the segments/pointer:

.game-container {
  position: relative;
  width: 300px;
  margin: 0 auto;
}

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

.wheel {
  width: 100%;
  height: 300px;
  border-radius: 50%;
  border: 4px solid #333;
  position: relative;
  transition: transform 3s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.segment {
  position: absolute;
  width: 50%;
  height: 50%;
  top: 0;
  right: 0;
  transform-origin: bottom left;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  box-sizing: border-box;
}

/* Optional: Stripe segments for better visibility */
.segment:nth-child(odd) {
  background-color: #f0f0f0;
}
.segment:nth-child(even) {
  background-color: #e0e0e0;
}

Key Adjustments for Your Specific Setup

  • Pointer Position: If your pointer isn't at the top, modify the adjustedAngle calculation. For example, a right-side pointer (90° clockwise from top) would use (360 - (finalRotation - 90)) % 360.
  • Rotation Direction: If your wheel spins counterclockwise, remove the 360 - part from the adjustedAngle formula.
  • Animation Timing: Adjust the CSS transition duration to match your desired spin length—this ensures the transitionend event fires at the correct moment.

内容的提问来源于stack exchange,提问作者shekhar ramola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 06:42:44