Spaces:
Sleeping
Sleeping
<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"> | |
<title>转盘抽奖</title> | |
<style> | |
*, | |
*::before, | |
*::after { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
html { | |
height: 100%; | |
background: #264563; | |
} | |
.luckdraw { | |
width: 300px; | |
height: 300px; | |
position: relative; | |
margin: 100px auto; | |
border-radius: 50%; | |
overflow: hidden; | |
} | |
.luckpanel { | |
position: relative; | |
width: 100%; | |
height: 100%; | |
transition: transform 3s ease-in-out; | |
} | |
#canvas { | |
position: relative; | |
width: 100%; | |
height: 100%; | |
} | |
#canvas .sector-item { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 50%; | |
height: 50%; | |
transform-origin: right bottom; | |
overflow: hidden; | |
} | |
/* #canvas .sector-item:nth-child(odd) { | |
background: pink; | |
} | |
#canvas .sector-item:nth-child(even) { | |
background: skyblue; | |
} */ | |
.prize { | |
position: absolute; | |
top: 0; | |
left: 50%; | |
width: 50%; | |
height: 50%; | |
transform: translateX(-50%); | |
} | |
.prize-item { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
transform-origin: center bottom; | |
} | |
.prize-item__name { | |
position: absolute; | |
top: 20px; | |
left: 10px; | |
width: calc(100% - 20px); | |
font-size: 12px; | |
text-align: center; | |
color: #ff572f; | |
} | |
.prize-item__img { | |
position: absolute; | |
top: 50px; | |
left: calc(50% - 30px /2); | |
width: 30px; | |
height: 30px; | |
} | |
.prize-item__img img { | |
width: 100%; | |
height: 100%; | |
vertical-align: bottom; | |
} | |
/* 抽奖 */ | |
.pointer { | |
position: absolute; | |
left: 50%; | |
top: 50%; | |
transform: translate(-50%, -50%); | |
width: 90px; | |
height: 90px; | |
background-color: orange; | |
border-radius: 50%; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
font-size: 30px; | |
font-weight: bold; | |
cursor: pointer; | |
user-select: none; | |
} | |
.pointer::after { | |
content: ''; | |
position: absolute; | |
top: -70px; | |
border: 40px solid orange; | |
border-left-width: 10px; | |
border-right-width: 10px; | |
border-left-color: transparent; | |
border-top-color: transparent; | |
border-right-color: transparent; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="luckdraw"> | |
<div class="luckpanel"> | |
<div id="canvas"></div> | |
<div class="prize"> | |
<!-- <div class="prize-item"> | |
<div class="prize-item__name">奖品</div> | |
<div class="prize-item__img"> | |
<img | |
src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.it168.com%2Fn%2F640x480%2F6%2F6414%2F6414197.jpg&refer=http%3A%2F%2Fimage.it168.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640667263&t=18bb80a694a5ff966713191b4a81745d" | |
alt=""> | |
</div> | |
</div> --> | |
</div> | |
</div> | |
<div class="pointer">抽奖</div> | |
</div> | |
<script> | |
const consts = { | |
// 奖品清单 | |
prizeList: [ | |
// { | |
// prizeName: '休息多5分钟', | |
// // prizeImg: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.it168.com%2Fn%2F640x480%2F6%2F6414%2F6414197.jpg&refer=http%3A%2F%2Fimage.it168.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640667263&t=18bb80a694a5ff966713191b4a81745d', | |
// count: 10, | |
// }, | |
// { | |
// prizeName: '休息多10分钟', | |
// // prizeImg: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.it168.com%2Fn%2F640x480%2F6%2F6414%2F6414197.jpg&refer=http%3A%2F%2Fimage.it168.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640667263&t=18bb80a694a5ff966713191b4a81745d', | |
// count: 5, | |
// }, | |
{ | |
prizeName: '托马斯1集', | |
// prizeImg: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.it168.com%2Fn%2F640x480%2F6%2F6414%2F6414197.jpg&refer=http%3A%2F%2Fimage.it168.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640667263&t=18bb80a694a5ff966713191b4a81745d', | |
count: 6, | |
}, | |
{ | |
prizeName: '丁丁1集', | |
// prizeImg: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.it168.com%2Fn%2F640x480%2F6%2F6414%2F6414197.jpg&refer=http%3A%2F%2Fimage.it168.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640667263&t=18bb80a694a5ff966713191b4a81745d', | |
count: 3, | |
}, | |
{ | |
prizeName: '小熊15分钟', | |
// prizeImg: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.it168.com%2Fn%2F640x480%2F6%2F6414%2F6414197.jpg&refer=http%3A%2F%2Fimage.it168.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640667263&t=18bb80a694a5ff966713191b4a81745d', | |
count: 5, | |
}, | |
{ | |
prizeName: '读书写字画画10分钟', | |
// prizeImg: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimage.it168.com%2Fn%2F640x480%2F6%2F6414%2F6414197.jpg&refer=http%3A%2F%2Fimage.it168.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640667263&t=18bb80a694a5ff966713191b4a81745d', | |
count: 2, | |
} | |
], | |
// 每一块扇形的背景色 | |
prizeBgColors: [ | |
'rgb(255,231,149)', | |
'rgb(255,247,223)', | |
'rgb(255,231,149)', | |
'rgb(255,247,223)', | |
'rgb(255,231,149)', | |
'rgb(255,247,223)', | |
'rgb(255,231,149)', | |
'rgb(255,247,223)', | |
], | |
// 每一块扇形的外边框颜色 | |
borderColor: '#ff9800' | |
} | |
const prizeNum = consts.prizeList.length | |
let itemAngle = 360 / prizeNum // 每个扇形区域的角度 | |
const offsetAngle = itemAngle / 2 | |
let isRotating = false | |
const circleCount = 3 // 旋转圈数 | |
const rotateDuration = 3 // 持续时间 | |
const panel = document.querySelector('.luckpanel') | |
// 画出扇形骨架 | |
function drawPanel() { | |
let fragMent = document.createDocumentFragment() | |
consts.prizeList.forEach((item, index) => { | |
let itemDom = document.createElement('div') | |
itemDom.setAttribute('class', 'sector-item') | |
itemDom.style.background = `${consts.prizeBgColors[index]}` | |
itemDom.style.borderBottom = `1px solid ${consts.borderColor}` | |
itemDom.style.transform = `rotate(${itemAngle * (index + 1)}deg) skewY(${90 - itemAngle}deg)` | |
fragMent.appendChild(itemDom) | |
}) | |
document.getElementById('canvas').appendChild(fragMent) | |
} | |
function getPrizeItem({ name, src }) { | |
const el = document.createElement('div') | |
let tpl = '' | |
if(src){ | |
tpl = ` | |
<div class="prize-item"> | |
<div class="prize-item__name">${name}</div> | |
<div class="prize-item__img"> | |
<img | |
src="${src}" | |
alt=""> | |
</div> | |
</div> | |
` | |
} | |
else{ | |
tpl = ` | |
<div class="prize-item"> | |
<div class="prize-item__name">${name}</div> | |
<div class="prize-item__img"> | |
</div> | |
</div> | |
` | |
} | |
el.innerHTML = tpl | |
return el.firstElementChild | |
} | |
// 填充奖品内容 | |
function fillPrize() { | |
const container = document.querySelector('.prize') | |
consts.prizeList.forEach((item, i) => { | |
const el = getPrizeItem({ | |
name: item.prizeName, | |
src: item.prizeImg | |
}) | |
// 旋转 | |
const currentAngle = itemAngle * i + offsetAngle | |
el.style.transform = `rotate(${currentAngle}deg)` | |
container.appendChild(el) | |
}) | |
} | |
// 获得哪一个奖品 | |
function getPrizeIndex(prizeList) { | |
// 中奖的是哪一个奖品 | |
let index = 0 | |
// 当前奖品总数量 | |
let prizeTotalNum = 0 | |
for (let i = 0; i < prizeList.length; i++) { | |
prizeTotalNum += prizeList[i].count | |
} | |
if (prizeTotalNum === 0) { | |
alert('奖品已抽完'); | |
return index = -1 | |
} | |
// 产生一个随机数 0-总数 | |
let random = parseInt(Math.random() * prizeTotalNum) | |
// 当前奖品的概率区间 | |
let currentWeight = 0 | |
for (let i = 0; i < prizeList.length; i++) { | |
currentWeight += prizeList[i].count | |
if (random < currentWeight) { | |
index = i | |
prizeList[i].count-- | |
break | |
} | |
} | |
return index | |
} | |
// 抽奖事件 | |
function bindEvent() { | |
document.querySelector('.pointer').addEventListener('click', function () { | |
if (isRotating) { | |
return | |
} else { | |
isRotating = true | |
} | |
const index = getPrizeIndex(consts.prizeList) | |
console.log('index', index); | |
if (index === -1) { | |
isRotating = false | |
} else { | |
console.log('奖品名称', consts.prizeList[index].prizeName); | |
rotate(index) | |
} | |
}) | |
} | |
// 旋转转盘 | |
let statrtRotatAngle = 0 | |
function rotate(index) { | |
// statrtRotatAngle % 360 上一次旋转到index的度数 | |
// statrtRotatAngle - statrtRotatAngle % 360 得到一个度数为 360*n | |
// 旋转到索引index商品的度数 | |
let angleToIndex = 360 - (offsetAngle + itemAngle * index) | |
const rotateAngle = statrtRotatAngle - statrtRotatAngle % 360 + circleCount * 360 + angleToIndex | |
statrtRotatAngle = rotateAngle | |
panel.style.transform = `rotate(${rotateAngle}deg)` | |
panel.style.transitionDuration = `${rotateDuration}s` | |
setTimeout(() => { | |
isRotating = false | |
}, 1000) | |
} | |
function init() { | |
// 画出扇形骨架 | |
drawPanel() | |
// 填充奖品内容 | |
fillPrize() | |
// 抽奖事件 | |
bindEvent() | |
document.onkeydown = function (event) { | |
if(event.key === 'm') | |
} | |
} | |
document.addEventListener('DOMContentLoaded', init) | |
</script> | |
</body> | |
</html> |