|
|
请马上登录,朋友们都在花潮里等着你哦:)
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 马黑黑 于 2022-4-26 19:14 编辑
关键词:forwards, 定格关键帧动画, @keyframes, JS, css
迄今为止,我们使用关键帧动画的方式都是循环(infinite)或循环+往复(infinite alternate)的,从未考虑和尝试过动画的定格。其实动画定格拥有足够多的应用场景,例如翻书就需要定格关键帧动画:一页书翻开后就让已完成的动作停住,否则我们就必须具备一目十行的阅读能力——显然这是多数人办不到的。本帖就以翻书为例,初步领略一下关键帧动画的定格设置。
我们先设计一个简单粗糙的书本样式。先看CSS部分:
.book {
margin: auto;
margin-top: 100px;
width: 700px;
height: 440px;
perspective: 1000px;
cursor: pointer;
border: 1px solid;
padding: 10px;
position: relative;
}
.page {
background: #ccc;
padding: 20px;
width: 310px;
height: 400px;
left: 50%;
border-left: 1px solid #eee;
transform-origin: left;
transform-style: preserve-3d;
position: absolute;
}
.book选择器其实是个容器,给书页提供存在与页翻页的场所,注意它设置了景深——翻书不能是2d的。为了便于观察,我们还设置了边框。
.page选择器就是书页了,注意设置了3d转换模式、转换基点,还有尺寸、定位等属性的设置都是根据.book选择器以及需要而定。
CSS代码还需要两个关键帧动画:
@keyframes rot1{
from { transform: rotateY(0deg); }
to { transform: rotateY(-180deg); }
}
@keyframes rot2{
from { transform: rotateY(-180deg); }
to { transform: rotateY(0deg); }
}
第一个是往后面翻页,第二个是往回翻页,注意二者 from 和 to 角度的变化。
深度简化的HTML代码如下:
<div class="book">
<div class="page" style="z-index:2">1</div>
<div class="page" style="z-index:1">2</div>
</div>
哎呀,我们这本书怎么才两页?管它呢,咱任性一回行不?再说了,书可不一定是越厚越好,在大力倡导节能减排的时代,我们要写薄而美的书。
到了这里,我们还没看到关键帧动画定格的影子。嗯,这是核心所在,我们这就讨论它。我们已经知道,关键帧动画的调用是元素通过animation属性实现的,比如我们已经熟知的下面的语句:
animation: rot1 2s linear infinite alternate;
使用上面语句的元素将调用名为 rot1 的关键帧动画(@keyframes rot1,我们此前设置的动画之一),即从 0deg 到 -180deg 沿Y轴旋转,2秒钟一个运行周期,匀速运行,重复运行,往复(亦即原路返回)运行。显然,这不是我们想要的翻书状态,所以,我们把它改为:
animation: rot1 0.5s linear forwards;
这将翻好书页后停住不动,定格在 rotateY(0deg) 到 rotateY(-180deg) 变换过程中的最后一帧(书页的翻转恰好是-180度,从0deg到-180deg有多少针是CSS和计算机的事情,我们所关心的仅是首帧和最后一帧)。forwards 本意是向前,在此表示向前定格(在最后一帧)。
OK,这是我们需要的,但如果在CSS代码流里某一个元素选择器中调用,则失去了交互性,它运行一次,停住。我们的期望是我们通过鼠标的交互操作来完成翻开书页的动作,这就需要用到JS了:
let page = document.querySelectorAll(".page"); //①首先……
let idx = 0; //②其次……
//③最后……
document.querySelector(".book").onclick = function(){
if(idx == 0){
page[0].style.animation = "rot1 .5s linear forwards";
idx = 1;
} else {
page[0].style.animation = "rot2 .5s linear forwards";
idx = 0;
}
}
①首先,获得书页数组,page变量通过 document.querySelectorAll() 内置函数得到所有书页的操作句柄(HTML里我们设置了两个页面),以数组形式存在,稍后我们将对第一页即 page[0] 进行翻过去再翻回来的操作。
②其次,我们声明了一个 idx 变量并给它赋值,这是将书页翻过去和翻回来的操作标识(依据),为0时翻过去,其他任何值时翻回来。
③最后,我们给书本的鼠标点击动作编写一个函数,该函数判断 idx 翻书行为标识值来决定调用 rot1 还是 rot2 关键帧动画,过程中还要修改 idx 的值以便下让一次的鼠标点击操作能有正确的结果。
animation的调用其实还是通过CSS实现,JS仅仅是控制什么时候让哪个元素运行什么动画、以什么方式运行动画,交互由此达成。并不是说CSS没有任何交互能力(想一想hover),但交互绝非CSS的特长,JS才是干这个的好手。
OK,大功告成,现在我们可以对第一页书页(其实应该是封面,缺少美工只好让它充当书页吧)进行交互性质的翻过来翻过去的操作了。
PS:从代码位置上看,forwards 虽然替代了 infinite|alternate,二者的地位却不是一样的:infinite|alternate设定动画执行的行为方式或特征(循环|往复);forwards 隶属于 animation-fill-mode 范畴,是动画的“填充”样式,它的“同僚”还有 none(默认)、backwards 和 both,它们实际上用于设定动画执行之前和(或)之后的状态,我们在此暂时不去对它们进行深入探讨。
效果在下面演示。
|
评分
-
| 参与人数 2 | 威望 +80 |
金钱 +160 |
经验 +80 |
收起
理由
|
加林森
| + 30 |
+ 60 |
+ 30 |
很给力! |
红影
| + 50 |
+ 100 |
+ 50 |
赞一个! |
查看全部评分
|