本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
少年,你相信命吗?来抽一签看看吧🐶
最近学会利用CSS实现伪随机效果,在知道源码的情况下,是可以推测出结果的,但是在用户不知情的情况下,就等同于随机。
效果
基本思路
主要是伪随机的思路:利用动画animation不断将radio元素改变位置,而用户点击判定的区域是固定,但因为动画的原因,造成每一次点击都不一定是相同的radio,从而实现伪随机效果。
如下图,绿色为可点击区域,红色为不同radio,radio不停的移动,造成每次选中的radio不一定相同:
代码
本文抽签效果中使用了10个radio,一个是重置按钮,九个是待选的签,而这九个待选的签又分为三组, 全部的radio都是同一个name。
因为要保证每次选中签之后,点击重置按钮可以获取新的结果,但是css中没有重置radio选中的功能,所以只能借助其另一个radio来实现重置。
- 重置按钮被选中的情况下,所有的签都执行动画,开始不停的改变自身的位置;如果重置按钮没有被选中,那么所有的签都停止动画,不再移动,将结果固定下来:
<!-- 默认选中重置按钮,让所有签执行动画,变换位置 -->
<input type="radio" id="resetBtn" name="label" checked="checked" />
<label for="resetBtn" class="reset-btn"> 重置 </label>
/* 重置按钮被选中时,其他radio都执行动画,改变位置 */
#resetBtn:checked ~ .labels .label {
animation-play-state: running;
}
因为将所有的签原本的动画状态设置为animation-play-state: paused;,所以此处就不需要再写上没选中时停止动画的样式。
2. 剩下的九个radio分为三组,每组三个radio,分别代表大吉、中吉、小吉;然后将每组的radio从上到下位置进行排序,根据上面的伪随机思路进行移动。
注意:每组中签的移动不能像平时一样有过度状态的执行,那样可能会导致同一个点击区域,点击不同的位置,会出现不同的结果,所以必须给动画加上
step-start或者step-end,让其按步骤执行。 其中一组布局如下:
<!-- 组 -->
<div class="labels labels-one">
<!-- 大吉 -->
<input type="radio" name="label" class="label very-lucky" />
<!-- 中吉 -->
<input type="radio" name="label" class="label lucky" />
<!-- 小吉 -->
<input type="radio" name="label" class="label little-lucky" />
<!-- 用于显示被选中radio -->
<div class="result"></div>
</div>
总体样式:
/* 标签组,同时也是可点击区域,设定位置、大小等 */
.labels {
width: 60px;
height: 100px;
background-color: #fbbf24;
overflow: hidden;
border-radius: 5px;
position: absolute;
top: 10px;
}
/* 组中每一个标签,设定与可点击区域一样大,方便点击 */
.label {
width: 60px;
height: 100px;
margin: 0;
/* 添加动画,设置为无线循环,按步骤执行 */
animation: roll 2s infinite step-end;
/* 将动画设置为暂停状态,实现重置按钮的逻辑 */
animation-play-state: paused;
cursor: pointer;
opacity: 0;
position: relative;
z-index: 10;
}
/* 位置改变动画 */
@keyframes roll {
0% {
transform: translateY(0);
}
33.33% {
transform: translateY(-100px);
}
66.66% {
transform: translateY(-200px)
}
}
/* 显示结果,如果本组的签没有被选中时,显示默认文字 */
.result::after {
content: '签';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
color: #ca8a04;
text-align: center;
line-height: 100px;
font-weight: bold;
font-size: 20px;
}
/* 组中不同radio被选中时,显示不同的结果 */
.very-lucky:checked ~ .result::after {
content: '大吉';
}
.lucky:checked ~ .result::after {
content: '中吉';
}
.little-lucky:checked ~ .result::after {
content: '小吉';
}
上面是三组签中其中一组,至于其他组,为了保证随机,可以改变大吉、中吉、小吉三种类型的顺序,设置不同动画执行时间,不同动画延迟时间等等。
详细代码请参照上面码上掘金的示例。