本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
用JS
写一个九格宫的抽奖程序并不难,但如果用css
写呢?本文记叙了用css
实现九格宫抽奖的过程。
效果
分析
把九格宫抽奖拆分一下,可以看成由两个部分组成:
- 奖品展示部分,抽奖的动画效果也是在这个部分完成;
这个部分除了展示奖品之外,还有一个抽奖的动画,当用户点击停止按钮时,停止动画,展示最终抽到的奖品,必须是一个奖品;
- 开始、停止按钮,供用户点击,决定什么时候停止抽奖。
按钮有两个状态,一个当前没有进行抽奖时,是开始按钮;当前进行抽奖时,是停止按钮。
代码
HTML
布局
这个布局比较讲究,因为抽奖有两个状态:抽奖进行中
和抽奖停止
。所以需要一个能在两个状态之间切换的元素,那就是<input type="checkbox" />
,它有选中和没有选中两个状态,刚好对应的抽奖的两个状态。
那么要使input
的选中状态能够影响抽奖动画,那么input
必须是奖品元素的父级或者同级元素,又因为input
需要伪装成按钮,所以本身要隐藏起来,借用别的元素进行伪装,所以只能是同级,布局如下:
<div class="box">
<!-- 实际按钮 -->
<input type="checkbox" id="btnInput" />
<!-- 帮input伪装按钮 -->
<label class="btn"></label>
<!--奖品展示区域-->
<div class="lattice">
<div> 1 </div>
<div> 2 </div>
<div> 3 </div>
<div> 4 </div>
<div> 5 </div>
<div> 6 </div>
<div> 7 </div>
<div> 8 </div>
<div> 9 </div>
</div>
</div>
复制代码
css
- 奖品区域,本文是使用
flex
和一个伪元素,来实现九格宫和抽奖动画的。九格宫比较简单,不再赘述。
动画是借助一个::after
,让其和每一个奖品的展示区域大小一样,然后不停的变换位置达到抽奖的效果。
而且位置变换时,不存在过度效果,这需要借助step-end
或者step-start
属性,它们可以让动画没有任何的过渡效果,在样式变化时直接展示改变后的效果。这样,无论在什么时候停下动画,都能确保选中一个奖品,样式如下:
.lattice::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
background-color: red;
/* 注意,这里设置了step-start */
animation: displacement 1s infinite step-start;
}
/* 动画比较简单,就是不停改变位置 */
@keyframes displacement {
0% {
top: 0;
left: 0;
}
11.1% {
top: 0;
left: 60px;
}
22.2% {
top: 0;
left: 120px;
}
33.3% {
top: 60px;
left: 0;
}
44.4% {
top: 60px;
left: 60px;
}
55.5% {
top: 60px;
left: 120px;
}
66.6% {
top: 120px;
left: 0;
}
77.7% {
top: 120px;
left: 60px;
}
88.8% {
top: 120px;
left: 120px;
}
}
复制代码
- 然后就是按钮,
<input>
和label
伪装成按钮比较简单,就是将两个元素重叠在一起,把input
的不透明度设置为零,然后将label
伪装成按钮,层级设置成低于input
,这样,用户以为是点击到label
伪装的按钮,实际上是点击到input
上,不再赘述。
但是本文是用label
的::after
来伪装成按钮,因为可以使用content
属性来更改按钮的文字,方便后续更改按钮的文字:
.btn::after {
/* 按钮文字,后续可以用content直接修改 */
content: '停止';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #f59e0b;
text-align: center;
line-height: 40px;
color: #fff;
}
复制代码
然后就是input
被选中时,需要停止动画,这个时候就用到动画的状态属性animation-play-state
,将其值改为paused
,则动画就会停止下来,样式如下:
/* 因为input与展示奖品元素是同级,但不是相邻,所以使用普通兄弟选择器 */
#btnInput:checked ~ .lattice::after {
/* 将动画状态该`paused`,停止动画 */
animation-play-state: paused;
}
复制代码
同理,在input
被选中时,更改按钮的文字:
扫描二维码关注公众号,回复:
14308715 查看本文章

#btnInput:checked + .btn::after {
/* 通过content可以修改文字。这也是为什么选择用伪元素的原因 */
content: '开始';
}
复制代码