如何使用JavaScript实现带自定义概率权重的转盘抽奖功能
转盘自定义中奖概率实现方案
你现有代码的逻辑是随机生成旋转角度,再匹配对应奖项,因为每个扇区固定45度,所以各奖项概率均等。要实现自定义概率,推荐优先用「预抽奖项再反向匹配角度」的方案,不用修改现有转盘UI,兼容性最好。
具体实现方案
方案1:权重映射法(无需修改转盘UI)
先按自定义概率抽中目标奖项,再计算对应的旋转角度,让转盘最终刚好停在目标奖项的扇区范围内,视觉上和随机旋转效果完全一致。
改造后的完整代码如下:
(function() { const wheel = document.querySelector('.wheel'); const startButton = document.querySelector('.button'); const display = document.querySelector('.display'); let deg = 0; const zoneSize = 45; // 现有转盘每个扇区固定45度,无需改动 // 奖项配置 const symbolSegments = { 1: "Frog", 2: "Snail", 3: "Dolphin", 4: "Ladybug", 5: "Koala", 6: "Unicorn", 7: "Dragon", 8: "Snowman", } // 自定义概率配置,总和需为100,可按需调整数值 const prizeProbability = { 1: 20, // 1号奖项20% 2: 10, // 2号奖项10% 3: 15, // 3号奖项15% 4: 15, // 4号奖项15% 5: 12, // 5号奖项12% 6: 10, // 6号奖项10% 7: 10, // 7号奖项10% 8: 8 // 8号奖项8% } // 按权重抽取中奖奖项 const getWinPrize = () => { const random = Math.random() * 100; let currentSum = 0; for (const prizeId in prizeProbability) { currentSum += prizeProbability[prizeId]; if (random < currentSum) { return Number(prizeId); } } return 1; // 容错处理,默认返回1号奖项 } const handleWin = (prizeId) => { display.innerHTML = symbolSegments[prizeId]; } startButton.addEventListener('click', () => { startButton.style.pointerEvents = 'none'; // 先确定中奖奖项 const winPrize = getWinPrize(); // 计算目标奖项对应角度区间的随机值,留2度余量避免卡在扇区分界线 const minDeg = (winPrize - 1) * zoneSize + 2; const maxDeg = winPrize * zoneSize - 2; const targetActualDeg = Math.floor(minDeg + Math.random() * (maxDeg - minDeg)); // 基础转15圈保证旋转效果自然,叠加目标角度得到最终旋转度数 const baseDeg = 360 * 15; deg = baseDeg + targetActualDeg; wheel.style.transition = 'all 10s ease-out'; wheel.style.transform = `rotate(${deg}deg)`; wheel.classList.add('blur'); }); wheel.addEventListener('transitionend', () => { wheel.classList.remove('blur'); startButton.style.pointerEvents = 'auto'; wheel.style.transition = 'none'; const actualDeg = deg % 360; wheel.style.transform = `rotate(${actualDeg}deg)`; const winPrize = Math.ceil(actualDeg / zoneSize); handleWin(winPrize); }); })();
方案2:不等宽扇区适配法(需同步修改转盘UI)
如果需要转盘扇区的视觉宽度和中奖概率成正比,可以采用该方案:
- 每个扇区的角度 = 360° * 对应奖项概率
- 提前存储每个奖项对应的角度起始、结束区间
- 抽中奖项后计算对应区间内的随机角度即可,核心逻辑和方案1一致,仅需将固定zoneSize改为动态计算的扇区角度。
内容的提问来源于stack exchange,提问作者Arun Bohra
相关产品推荐
相关产品推荐

