代码由 HTML、CSS 和 JavaScript 三部分组成,HTML 负责页面的结构搭建,CSS 负责页面的样式设计,JavaScript 负责实现抽奖的交互逻辑。
HTML 部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./assets/global.css">
<!-- 内联样式 -->
<style>
/* 样式规则 */
</style>
</head>
<body>
<div class="prize-container">
<!-- 奖品项 -->
<div class="prize-item" style="left: 0;top: 0;"></div>
<!-- ... 其他奖品项 ... -->
<div class="prize-turn" style="left: 200px;top: 200px;">开始转动</div>
</div>
<script type="module">
// JavaScript 代码
</script>
</body>
</html>
<!DOCTYPE html>
:声明文档类型为 HTML5。<html>
:根元素,lang="en"
表示页面语言为英语。<head>
:包含页面的元数据,如字符编码、兼容性设置、视口设置,还引入了外部样式表./assets/global.css
,并定义了内联样式。<body>
:页面的主体部分,包含一个prize-container
容器,其中有 8 个prize-item
元素表示奖品项,一个prize-turn
元素作为开始转动的按钮。<script>
:引入 JavaScript 代码,type="module"
表示使用 ES6 模块语法。
CSS 部分
.prize-container {
position: relative;
}
.prize-container .prize-item,
.prize-container .prize-turn {
position: absolute;
width: 200px;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
box-sizing: border-box;
}
.prize-container .prize-turn {
background-color: #fff;
cursor: pointer;
border-radius: 50%;
border: 1px solid rgb(209, 92, 92);
font-size: 30px;
transform: scale(.5, .5);
color: rgb(209, 92, 92);
transition: all .4s ease-in;
}
.prize-container .prize-item {
border: 4px solid transparent;
}
.prize-container .prize-item img {
width: 100%;
height: 100%;
object-fit: cover;
opacity: .9;
}
.prize-container .prize-item>div {
position: absolute;
width: 100%;
text-align: center;
left: 0;
font-weight: bold;
color: beige;
line-height: 30px;
bottom: 0;
background-color: rgba(0, 0, 0, .3);
}
.prize-container .prize-turn:active {
background-color: rgb(209, 92, 92);
color: #fff;
}
.prize-container .prize-item.active {
border-color: #eb9c26;
}
.prize-container
:设置为相对定位,作为奖品项和转动按钮的父容器。.prize-item
和.prize-turn
:设置为绝对定位,固定宽度和高度,使用 flex 布局使其内容居中,禁止用户选择文本。.prize-turn
:设置为白色背景,圆形,有边框和文字颜色,点击时背景和文字颜色会发生变化。.prize-item
:初始边框为透明。.prize-item img
:设置图片宽度和高度为 100%,保持图片比例并覆盖整个容器,透明度为 0.9。.prize-item > div
:设置奖品名称的样式,位于图片底部,有半透明背景。.prize-item.active
:当奖品项处于激活状态时,边框颜色变为#eb9c26
。
JavaScript 部分
import { Maths, Randoms, Animation } from "https://unpkg.com/@3r/tool"
// 获取所有的奖品项和转动按钮
let prizeDomList = document.querySelectorAll('.prize-item')
let prizeTurnDom = document.querySelector('.prize-turn')
let startIndex = 0;
// 奖品列表
let prizes = [
{
name: '苹果13',
weight: 1,
imgSrc: './assets/prizes/1.jpg'
},
// ... 其他奖品 ...
]
// 展示奖品信息
for (let i = 0; i < prizeDomList.length; i++) {
const prizeItem = prizeDomList[i];
const prizeText = document.createElement('div')
const prizeImage = document.createElement('img')
prizeText.textContent = prizes[i].name
prizeImage.setAttribute("src", prizes[i].imgSrc)
prizeItem.appendChild(prizeImage)
prizeItem.appendChild(prizeText)
}
// 等待时间函数
let waitTime = function (time) {
return {
then: function (resolve) {
setTimeout(resolve, time)
}
}
}
// 转动函数
let turn = async function () {
let offset = 1 / (prizes.length * 10) // 执行次数
let interval = 200; // 延迟
let minInterval = 50; // 最小延迟
let endIndex = Randoms.getRandomIndexByWeight(prizes) // 随机结束奖品
let lastDom = null
for (let i = 0; i <= 1; i += offset) {
// 延迟时间
await waitTime(Math.max(Animation.easeIn(i) * interval, minInterval))
lastDom?.classList?.remove('active');
lastDom = prizeDomList.item(startIndex % prizeDomList.length)
lastDom.classList.add('active')
if (i > .9 && (startIndex % prizeDomList.length === endIndex)) break;
startIndex++;
}
let name = prizes[endIndex].name
setTimeout(() => {
if (name == "再来一次")
alert(`请${name}吧~`)
else
alert(`您获得了${name}`)
}, interval);
}
// 点击事件监听
prizeTurnDom.addEventListener("click", turn)
- 导入模块 :从
https://unpkg.com/@3r/tool
导入Maths
、Randoms
和Animation
模块。 - 获取元素 :使用
querySelectorAll
和querySelector
获取所有奖品项和转动按钮。 - 奖品列表:定义了一个包含 8 个奖品的数组,每个奖品有名称、权重和图片路径。
- 展示奖品信息:遍历奖品项,为每个奖品项创建图片和名称元素,并添加到对应的奖品项中。
- 等待时间函数 :
waitTime
函数返回一个对象,包含then
方法,用于实现异步延迟。 - 转动函数 :
turn
函数实现了抽奖的转动逻辑,通过Randoms.getRandomIndexByWeight
方法根据权重随机选择一个奖品,然后循环遍历奖品项,逐渐增加激活状态的奖品项,直到达到随机选择的奖品项。 - 点击事件监听 :为转动按钮添加点击事件监听器,点击时调用
turn
函数。
效果展示