本文首发于:github.com/bigo-fronte… 欢迎关注、转载。
本文由bigo前端翻译小组翻译,原文链接:Whack-a-Mole: The CSS Edition
前言
我们之前介绍过如何对checkbox改造(译者注:“checkbox hack”,即通过隐藏checkbox标签,展示lable标签,并用for属性将两者关联,最后根据checkbox上的CSS伪类选择器“:checked”来区分以及定义各种状态),来实现一个纯CSS的完全状态机。今天我们将沿着这个思路打造一个简单的打地鼠游戏,游玩者需要反应足够迅速才能赢得游戏,而这些所有的实现都不需要用到JavaScript。
一门编程语言如果不包含计时器相关的功能(timer、interval)看上去似乎有点傻,但CSS具有类似的功能,秘密就隐藏在CSS动画中。
请看下面这个例子,注意CSS是无法识别一个点击事件的,更不用说一个双击事件:
那上面这个例子是怎么做到的呢?下面我们把实现例子的主要元素换个颜色并放慢速度看看:
思路是,当你第一次点击按钮时,可以将另一个元素(double-click)放置在鼠标下面,用来响应第二次的点击,同时会有一个蒙板元素由下往上移动,最终覆盖第二个元素(double-click),那么:
- 如果第二次点击足够快(如上图左边所示),点击就会发生在double-click元素上(蓝色背景)。
- 否则(如上图右边所示),点击会发生在蒙版,single-click元素上(黄色背景),这时不做处理,效果就如同单次点击。
(更多与之相关的解释可以在我写的纯CSS双击处理器文章中查看)
结合这个思路,可以有以下技巧来实现我们的地鼠游戏:
- 使用一组预先设置好的动画模式来管理状态(这里宽泛地将其称为“状态”)。
- 通过改变元素的位置,我们可以限制用户是否允许进行操作。
这就是我们所需要的!
对于地鼠的动作,利用元素的滚动(scroll)是一种实现方式,但我们也可以利用动画的属性animation-timing-function: step-end,来实现地鼠的出现与消失:
试过一些不同的方法去移开地鼠后,发现改变其绝对位置似乎是最好的方案。使用移动或许更加方便,但不幸的是在firefox上达不到效果,因为改变transform并不会引起重排,所以firefox会认为当前鼠标并没有击中地鼠,这在通常情况下可以有助于提高性能,但对于我们这个小demo则意义不大。
然后加上一些样式,我们可以使它看上去更像一个游戏:
地鼠实际上是一个label元素,进行了一定的样式化处理,它会触发checkbox hack,同样地鼠洞也是一样的处理。当地鼠由于动画出现在洞中的时候,通过点击它会触发地鼠对应的checkbox,当地鼠由于动画不在洞中时,点击就会触发地鼠洞对应的checkbox。(译者注:通过触发不同的checkbox,根据css上checkbox的checked伪选择器,可以设置不同的样式,达到状态管理的效果。)
下一步则是生成一排地鼠洞,以及多个地鼠,并让他们从洞里面跳出来,同时赋予他们不同的动画延迟。最后结合状态机,判断哪个地鼠被击中了,哪个洞穴被破坏了,就实现了一个简单的打地鼠小游戏。
这里我们使用了python来生成上面说的地鼠动画关键帧,以及地鼠与地鼠洞的各个状态,因为如果全部手写的话就太麻烦了。同时由于CSS没有随机数的概念,所以地鼠的“随机”运动实际上是通过硬编码定义keyframe来实现的。
至此一个完全基于反应并仅使用了html和css的游戏就完成了。
欢迎大家留言讨论,祝工作顺利、生活愉快!
我是bigo前端,下期见。