前言
新一季的 Rick&Morty 已经上线,剧集质量虽然有所下降,但 E03 中的 SheepCounter 挺有意思。自己照着剧中的设定开发了一款界面极其相似、交互更为丰富的小程序,小程序的终极目标只有一个:数羊!数羊!!数羊!!!。
不会真有人觉得这款小程序会起到催眠作用吧。
小程序虽然简单,但也探索出了一些有意思的小实现。下面就和大家分享探讨一下:
曲线路径的动画实现
首先就是小羊跳入、跳出界面的动画,仔细观察地话可以发现,小羊移动的路径其实是条曲线。
水平或者垂直移动的动画不难实现,我们可以通过控制绝对定位下的 left/right 或者 top/bottom 来实现。
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><title></title><meta name="description" content="" /><meta name="viewport" content="width=device-width, initial-scale=1" /><style> .zone {position: relative;width: 200px;height: 400px;top: 100px;left: 400px;border: 1px solid red;}.ball {position: absolute;width: 50px;height: 50px;background-color: cadetblue;border-radius: 50%;top: 30px;right: -100px;animation: XIn 1s linear;animation-fill-mode: forwards;}@keyframes XIn {0% {right: -100px;}100% {right: 50%;}} </style></head><body><div class="zone"><div class="ball"></div></div></body>
</html>
如果是需要曲线移动呢?animation 中似乎没有可以设置曲线移动的属性。不过我们可以参照高中物理知识思考一下,二维平面上移动无外乎水平或者垂直两个方向,当两个方向的移动同时发生且速度不一致时,便可以合成为曲线运动。结合此原理,我们可以轻松地想到:只要在animation中同时设置速度不一致的垂直移动动画和水平移动动画即可。
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><title></title><meta name="description" content="" /><meta name="viewport" content="width=device-width, initial-scale=1" /><style> .zone {position: relative;width: 200px;height: 400px;top: 100px;left: 400px;border: 1px solid red;}.ball {position: absolute;width: 50px;height: 50px;background-color: cadetblue;border-radius: 50%;top: 30px;right: -100px;animation: XIn 1s cubic-bezier(0.28, 0.58, 0.4, 0.73), YIn 1s linear;animation-fill-mode: forwards;}@keyframes XIn {0% {right: -100px;}100% {right: 50%;}}@keyframes YIn {0% {top: 30px;}100% {top: 50%;}} </style></head><body><div class="zone"><div class="ball"></div></div></body>
</html>
这样也就成功实现了曲线移动效果。
自定义输入框的实现
可以看到,在我们小程序的数羊界面中已经有了自定义实现了键盘。在小程序中进行输入时,我们肯定不希望弹起系统键盘。
输入框最有辨识度的特点是什么?那自然是闪烁的光标。光标才可以为我们自定义的输入框注入灵魂。闪烁效果其实也只是个动画而已,以下是简单的实现效果:
.sCursor {position: absolute;display: inline-block;width: 3px;height: 50px;margin-left: 4px;background: #000;top: 24px;animation: blink 800ms infinite reverse;
}
@keyframes blink {0% {opacity: 1;}100% {opacity: 0;}
}
<View className={style.sInput}>{/* <!-- 文本 --> */}{inputValue?.split('').map((v: string, i: number) => (<Text key={i} className={style.sValue}>{v} </Text> ))} {/* <!-- 光标 --> */}<View className={style.sCursor} />
</View>
为了避免用户忘记了自己数到了第几只羊,我决定在用户输入错误两次后,用placeholder的形式来提示用户。自定义placeholder的思路也非常简单,只需要将其绝对定位至正常输入的文本之下:
.inputZone {width: 500px;height: 100px;position: relative;.sInput {width: 100%;height: 100%;padding: 10px 40px;letter-spacing: 6px;position: relative;.sValue {font-size: 60px;font-family: 'handwriting';}.sCursor {//...}}.sTip {position: absolute;font-size: 60px;font-family: 'handwriting';z-index: 1;top: 10px;left: 40px;color: rgb(145, 142, 142);}
}
<View className={style.inputZone}><View className={style.sInput}>{/* <!-- 文本 --> */}{inputValue?.split('').map((v: string, i: number) => (<Text key={i} className={style.sValue}>{v}</Text>))}{/* <!-- 光标 --> */}<View className={style.sCursor} /></View>{tip && !inputValue ? (<Text className={style.sTip}>{tip}</Text>) : null}
</View>
键盘功能的实现就更简单了,只需要根据不同按钮点击事件触发相应的功能就行。想必大家都能想到,这里不贴代码了。
尾言
兴趣是学习的最好老师。一款看起来极其简单的小程序,真正实践开发起来也能遇到一些未曾了解过的知识点。Xdm,如果你也有有趣的点子,别犹豫,行动起来吧!
最后插一句,希望Rick&Morty后续剧集的质量能upup!!
最后
整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。
有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享
部分文档展示:
文章篇幅有限,后面的内容就不一一展示了
有需要的小伙伴,可以点下方卡片免费领取