突然想写个react的九宫格抽奖组件,就浅尝一下。写个demo玩玩.
0.5秒随机点亮奖项,按提供的奖品数组抽奖几率来决定最终中奖;
const items = [
{ id: 1, text: "谢谢惠顾", probability: 0.2 },
{ id: 2, text: "谢谢惠顾", probability: 0.2 },
{ id: 3, text: "谢谢惠顾", probability: 0.2 },
{ id: 4, text: "五等奖", probability: 0.15 },
{ id: 5, text: "四等奖", probability: 0.15 },
{ id: 6, text: "三等奖", probability: 0.09 },
{ id: 7, text: "二等奖", probability: 0.006 },
{ id: 8, text: "一等奖", probability: 0.003 },
{ id: 9, text: "特等奖", probability: 0.001 },
];
import React, { useState, useEffect } from "react";
import "./index.css";
const PrizeGrid = ({ items }) => {
const [selected, setSelected] = useState(null);
const [isRunning, setIsRunning] = useState(false);
useEffect(() => {
let timerId;
if (isRunning) {
timerId = setInterval(() => {
const randomIndex = Math.floor(Math.random() * 9);
console.log(randomIndex);
setSelected(randomIndex);
}, 500);
}
return () => clearTimeout(timerId);
}, [isRunning, selected]);
const handleClick = () => {
if (isRunning) return;
setIsRunning(true);
setTimeout(() => {
setIsRunning(false);
const randomIndex = selectWinner(items);
console.log("最后中奖", randomIndex);
setSelected(randomIndex);
}, 6000);
};
// 按奖品中奖几率抽奖逻辑
const selectWinner = (itemsArr) => {
const probabilities = itemsArr.map((item) => item.probability);
const sum = probabilities.reduce((acc, val) => acc + val, 0);
const normalizedProbabilities = probabilities.map((p) => p / sum);
let cumulativeProbability = 0;
const cumulativeProbabilities = normalizedProbabilities.map((p) => {
cumulativeProbability += p;
return cumulativeProbability;
});
const randomNumber = Math.random();
const selectedIndex = cumulativeProbabilities.findIndex(
(cp) => randomNumber <= cp
);
return selectedIndex + 1;
};
return (
{items.map((item, index) => (
{item.text}
))}
);
};
export default PrizeGrid;
index.css
.prize-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
margin: 20px;
width: 300px;
height: 300px;
}
.prize-grid-item {
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
width: 100px;
height: 100px;
border-radius: 50%;
background-color: #eee;
color: #333;
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3);
transition: background-color 0.3s ease-in-out;
}
.prize-grid-item.selected {
background-color: rgb(223, 113, 10);
}
.prize-grid-button {
margin: 20px auto;
display: block;
padding: 10px;
background-color: #00f;
color: #fff;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
}
还有其他的按照几率来随机中奖的工具方法,比如:
概率数组法:将所有奖品的概率存入一个数组中,然后生成一个随机数,根据随机数的值在概率数组中查找对应的奖品。
区间法:将所有奖品的概率转化为区间,然后生成一个0到1之间的随机数,在对应的区间内查找对应的奖品。
权重随机法:将所有奖品按照权重分配一个区间,然后生成一个随机数,根据随机数落在哪个区间来确定中奖的奖品。
这些方法都可以根据具体的需求来选择适合的方法。
function getRandomIndexByProbability(probabilityList) {
const totalProbability = probabilityList.reduce((a, b) => a + b, 0); // 计算总概率
let random = Math.random() * totalProbability; // 生成随机数
for (let i = 0; i < probabilityList.length; i++) { // 循环概率数组
random -= probabilityList[i]; // 减去当前奖品的概率
if (random < 0) { // 判断是否中奖
return i; // 返回中奖的奖品索引
}
}
}
function getRandomIndexByInterval(intervalList) {
const random = Math.random(); // 生成随机数
let probability = 0;
for (let i = 0; i < intervalList.length; i++) { // 循环区间数组
if (random >= probability && random < intervalList[i]) { // 判断是否中奖
return i; // 返回中奖的奖品索引
}
probability = intervalList[i]; // 记录上一个区间的概率
}
}
function getRandomIndexByWeight(weights) {
const totalWeight = weights.reduce((a, b) => a + b, 0); // 计算总权重
let random = Math.random() * totalWeight; // 生成随机数
for (let i = 0; i < weights.length; i++) { // 循环权重数组
random -= weights[i]; // 减去当前奖品的权重
if (random < 0) { // 判断是否中奖
return i; // 返回中奖的奖品索引
}
}
}
点赞加关注哦!!!