Author: front impression, link: mp.weixin.qq.com/s/PNEbCNR2b…
Basic CSS implementation, no images, add a throw JS. No consideration for compatibility at all. Let me draw a turntable
<! < HTML >< HTML lang="en"> <head> <meta charset=" utF-8 "> <title> </title> <style> /* reset default style */ * {margin: 0; padding: 0; border: none; outline: none; } .wrapper { position: relative; height: 200px; width: 200px; padding: 20px; margin: 20px; background-color: #c0381f; box-shadow: #000000 0px 0px 10px; border-radius: 50%; } .panel { position: relative; height: 200px; width: 200px; background-color: #b7b7b7; border-radius: 100px; } .pointer { position: absolute; left: 79px; top: 79px; z-index: 10; height: 30px; width: 30px; padding: 6px; color: #fff899; line-height: 15px; font-size: 12px; text-align: center; background-color: #dc5b5b; border-radius: 50%; border: 1px solid #c0381f; </style> </head> <body> <div class="wrapper"> <div class="panel"> <div class="pointer"> start drawing </div> </div> </div> </body> </html>Copy the code
The effect is as follows, don’t worry about color matching, it may be ugly…
Then write the small arrow of the lottery pointer. Drawing a triangle with CSS is a common problem, by setting width and height to 0 and then using border.
As shown in the figure, the rectangle is made up of four triangular borders. Separate triangles can be obtained by setting the color of the other sides to transparent. Here the triangle is implemented with the pseudo-element After, and the triangle is positioned at the top of the small circle in the middle by absolute positioning.
.pointer::after {
content: '';
position: absolute;
left: 14px;
top: -24px;
border-width: 12px 6px;
border-style: solid;
border-color: transparent;
border-bottom-color: #c0381f;
}
Copy the code
Oh next is the realization of the turntable background, different sectors corresponding to different prizes, so there is a requirement: implementation of arbitrary Angle fan.
You might think that it is the same as the triangle, just add a border-radius, the height is the radius of the circle, the width is tan(θ/2), but the effect is not as imagined… (I might have to do something else to make it work, but I didn’t think of it. Finally, I turned to a search engine. I have to admit that the Dalaos are very nb, Qaq… Getting ideas through Linear-gradient is awesome. But there are a lot of complicated implementations that don’t make much sense
ow to draw a circle sector in CSS?
Segments in a circle using CSS3
Three kinds of pure CSS to achieve hollow in the middle of the 12 color rainbow gradient ring method is to take the intersection of two squares.
I think the picture is quite good 😀
I didn’t use a fake element, because I’m going to add text, and I’m really messing around with where the text is, because I don’t write real code like that
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> .sector { position: absolute; width: 100px; height: 200px; margin: 100px; border-radius: 0px 100px 100px 0; overflow: hidden; transform: rotate(-18deg); } .sector-inner { text-align: center; display: block; width: 40px; padding: 5px 3px 0 57px; height: 195px; background: #ffeab1; transform: translateX(-100px) rotate(36deg); transform-origin: right center; border-radius: 100px 0 0 100px; } .sector-inner span { display: block; transform-origin: center; transform: rotate(-19deg); color: #d46854; } </style> </head> <body> <div class="sector"> <div class="sector-inner"> </html>Copy the code
It looks like this: a small sector with text ~~
OK, so now I’m going to write a bunch of scallops and put them on the wheel at the beginning.
The current code is too long. Fold it.
Now the CSS section of the turntable is almost complete. Let me just write the JS part. Click the middle pointer, the pointer will turn, you can pull a Bezier curve, control the speed of animation.
The Bezier curve can simply be thought of as a time-distance curve, and the slope is the velocity. Because the speed of the wheel must be fast then slow, pull any one.
Add attributes to the CSS
.pointer { // ... The transition: transform 3 s cubic - the bezier (43, 1. 2. 93.); }Copy the code
When clicking to start the draw, add a rotation Angle to the middle pointer. One of the problems here is that different sectors have the same probability of drawing, so if you change it to different sectors you should… Also pretty simple, but mainly want to practice CSS, JS write casually.
JS part of the code.
let getEle = document.getElementsByClassName.bind(document); let pointer = getEle('pointer')[0]; let result = getEle('result')[0]; let onRotation = false; // Record whether the current rotation, if the rotation, Cannot continue to click the let reward = [' thank you to participate in ', '50 points',' thank you to participate in ', '100 yuan of money,' 50 points', 'thank you to participate in', '100 yuan of money,' thank you to participate in ', '50 points',' 10 yuan money]. Function () {currentDeg = 0; Return function() {let rotateDeg = math.random () * 360 + 1080; currentDeg += rotateDeg; let rewardText = reward[Math.floor((currentDeg + 18) % 360 / 36)] return { deg: currentDeg, text: RewardText === 'Thanks for playing'? 'I'm sorry you didn't get the prize. + rewardText}}})(); pointer.addEventListener('click', () => { if (onRotation) return; Console. log(' start lottery '); onRotation = true; let nextStatus = getReward(); console.log(nextStatus) result.innerText = nextStatus.text; result.style.display = 'none'; pointer.style.transform = `rotateZ(${nextStatus.deg}deg)`; }) pointer.adDeventListener (' TransitionEnd ', () => {console.log(' lottery end'); onRotation = false; result.style.display = 'block'; })Copy the code
Now that a lottery wheel is almost complete, the last requirement, if the next waiting can be lit up. As to how bright light, you need to use CSS 3 animation, I’m not very familiar with, first to learn > _ < I learned back, refer to the tutorial www.ruanyifeng.com/blog/2014/0… It’s not very much.
animation-name
Specify the animation name,animation-duration
Specify the animation duration,animation-timing-function
Specify the animation function, which is the same as the transition function,animation-delay
Specify how long to delay animation execution,animation-iteration-count
Specifies how many times the animation is executed. The default is once. You can specify infinite.animation-direction
Specifies if the animation is played multiple times, it ends once and ends the next time.
Animation-fence-mode specifies where animations will be stopped after they are finished. Default is back to the start state. Forward means to stay at the end state, backwards means to move animations back to the first frame. Both uses forwards and backwards rules in rotation according to Animation-direction.
Animation-play-state Specifies the animation execution state. The default value is RUNNING and the pause value can be set to pause. The animation will stop in the current state.
Use the keyword keyframes to define an animation. Specify any of these states by percentage.
So let’s try to write theta. =
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> div { height: 30px; width: 30px; animation: 1s twinkling 3, 100ms 3s twinkling 3; } @keyframes twinkling { 50% { background: red; } } </style> </head> <body> <div></div> </body> </html>Copy the code
This is a square that blinks slowly three times, then blinks fast three times, then disappears.
animation: 1s twinkling 3;
Is equivalent to
animation-name: twinkling;
animation-duration: 1s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 3;
animation-direction: normal;
animation-fill-mode: none;
animation-play-state: running;
Copy the code
Finally, add the animation to the light on the turntable. Finished the code (it looks like the color has changed, well, that’s because I learned the animation for too long and the color has faded) :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>幸运大转盘</title>
<style>
* { /* 重置默认样式 */
margin: 0;
padding: 0;
border: none;
outline: none;
user-select: none;
}
.wrapper {
position: relative;
height: 200px;
width: 200px;
padding: 20px;
margin: 20px;
background-color: #ff5555;
box-shadow: #000000 0px 0px 10px;
border-radius: 50%;
}
.light {
position: absolute;
height: 10px;
width: 10px;
border-radius: 50%;
top: 5px;
left: 115px;
transform-origin: 5px 115px;
}
.light-twinkling {
animation: 1s twinkling 3, 100ms 3s twinkling 3;
}
.light:nth-child(2n) {
background-color: #fafce7;
}
.light:nth-child(2n+1) {
background-color: #ffe58b;
}
.light:nth-child(2) {
transform: rotate(36deg);
}
.light:nth-child(3) {
transform: rotate(72deg);
}
.light:nth-child(4) {
transform: rotate(108deg);
}
.light:nth-child(5) {
transform: rotate(144deg);
}
.light:nth-child(6) {
transform: rotate(180deg);
}
.light:nth-child(7) {
transform: rotate(216deg);
}
.light:nth-child(8) {
transform: rotate(252deg);
}
.light:nth-child(9) {
transform: rotate(288deg);
}
.light:nth-child(10) {
transform: rotate(324deg);
}
.panel {
position: relative;
height: 200px;
width: 200px;
background-color: #b7b7b7;
border-radius: 100px;
}
.sector {
position: absolute;
left: 100px;
top: 0px;
width: 100px;
height: 200px;
font-size: 14px;
border-radius: 0px 100px 100px 0;
overflow: hidden;
transform-origin: left center;
}
.sector:nth-child(1) {
transform: rotate(-18deg);
}
.sector:nth-child(2) {
transform: rotate(18deg);
}
.sector:nth-child(3) {
transform: rotate(54deg);
}
.sector:nth-child(4) {
transform: rotate(90deg);
}
.sector:nth-child(5) {
transform: rotate(126deg);
}
.sector:nth-child(6) {
transform: rotate(162deg);
}
.sector:nth-child(7) {
transform: rotate(198deg);
}
.sector:nth-child(8) {
transform: rotate(234deg);
}
.sector:nth-child(9) {
transform: rotate(270deg);
}
.sector:nth-child(10) {
transform: rotate(306deg);
}
.sector:nth-child(2n+1) .sector-inner {
background: #fef6e0;
}
.sector:nth-child(2n) .sector-inner {
background: #ffffff;
}
.sector-inner {
text-align: center;
display: block;
width: 40px;
padding: 5px 3px 0 57px;
height: 195px;
transform: translateX(-100px) rotate(36deg);
transform-origin: right center;
border-radius: 100px 0 0 100px;
}
.sector-inner span {
display: block;
transform-origin: center;
transform: rotate(-19deg);
color: #d46854;
}
.pointer {
position: absolute;
left: 79px;
top: 79px;
z-index: 10;
height: 30px;
width: 30px;
padding: 6px;
color: #fff899;
line-height: 15px;
font-size: 12px;
text-align: center;
background-color: #ff5350;
border-radius: 50%;
border: 1px solid #ff5350;
transition: transform 3s cubic-bezier(.2,.93,.43,1);
}
.pointer::after {
content: '';
position: absolute;
left: 14px;
top: -24px;
border-width: 12px 6px;
border-style: solid;
border-color: transparent;
border-bottom-color: #ff5350;
transform-origin: center;
}
.result {
margin: 20px 60px;
}
@keyframes twinkling {
50% { background: transparent; }
}
</style>
</head>
<body>
<div class="wrapper">
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
<div class="panel">
<div class="sector">
<div class="sector-inner">
<span>谢谢参与</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span> 5 0 积分</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span>谢谢参与</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span>100元话费</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span> 5 0 积分</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span>谢谢参与</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span>100元话费</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span>谢谢参与</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span> 5 0 积分</span>
</div>
</div>
<div class="sector">
<div class="sector-inner">
<span>10元话费</span>
</div>
</div>
<div class="pointer">开始抽奖</div>
</div>
</div>
<div class="result"></div>
<script>
let getEle = document.getElementsByClassName.bind(document);
let pointer = getEle('pointer')[0];
let result = getEle('result')[0];
let lights = Array.prototype.slice.call(getEle('light'));
let onRotation = false; // 记录当前是否正在旋转,如果正在旋转,就不能继续点击了
let reward = ['谢谢参与', '50积分', '谢谢参与', '100元话费', '50积分',
'谢谢参与', '100元话费', '谢谢参与', '50积分', '10元话费'];
// 根据随机角度获取奖励
let getReward = (function() {
currentDeg = 0;
return function() {
// 转三圈到四圈
let rotateDeg = Math.random() * 360 + 1080;
currentDeg += rotateDeg;
let rewardText = reward[Math.floor((currentDeg + 18) % 360 / 36)]
return {
deg: currentDeg,
text: rewardText === '谢谢参与' ? '很遗憾,您没有获得奖品。' : '恭喜获得: ' + rewardText
}
}
})();
pointer.addEventListener('click', () => {
if (onRotation) return;
console.log('开始抽奖');
onRotation = true;
lights.forEach(light => { light.className += ' light-twinkling'; });
let nextStatus = getReward();
console.log(nextStatus)
result.innerText = nextStatus.text;
result.style.display = 'none';
pointer.style.transform = `rotateZ(${nextStatus.deg}deg)`;
})
pointer.addEventListener('transitionend', () => {
console.log('抽奖结束');
setTimeout(() => { // 等闪烁三下结束
onRotation = false;
lights.forEach(light => { light.className = 'light'; });
result.style.display = 'block';
}, 300);
})
</script>
</body>
</html>
Copy the code