animation-fill-mode は CSS3 アニメーションのプロパティで、アニメーションの実行前と完了後の要素のスタイルを制御できます。遅延を伴うアニメーションを通常の方向 (通常の方向とは 0% から 100% まで実行することを指します) で実行すると、実行プロセスは次のように記述できます。
アニメーションの実行時間に応じて分割され、アニメーション処理要素は、アニメーション待機状態、アニメーション進行状態、アニメーション終了状態の 3 つの状態に分類できます。デフォルトでは、アニメーションのキーフレームによって定義されたスタイルは、アニメーションの進行中およびアニメーションの待機状態およびアニメーションの終了状態にあるときにのみ適用され、要素のスタイルには影響しません。 anime-fill-mode には次の 4 つの値があります。
none: これは、アニメーションが完了するまで待機している要素のスタイルを変更しないようにするデフォルト値です。この値に設定した場合、アニメーションが待機している間、要素のスタイルはアニメーションの最初のフレームのスタイルに設定されます
forwards: この値に設定した場合、アニメーションの終了後。 、要素のスタイルはアニメーションのスタイルに設定されます。 最後のフレームのスタイル
両方: これは、アニメーションの待機状態とアニメーションの終了状態を同時に設定することと同じです。の場合、要素はアニメーションの最初と最後のフレームのスタイルをそれぞれ適用します。
以下のデモを通じて、animation-fill-mode の 3 つの非なしの値の効果を感じることができます。
アニメーションフィルモードに関するいくつかの考え: http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#アニメーションフィルモードに関するいくつかの考え効果は次のとおりです:
ソースコードが不要:
りー
在以上demo中,定义了一个move_1的动画,它包含三个关键帧,第一帧让元素往左偏移50px,最后一帧让元素往右偏移50px,这个偏移都是相对元素的初始状态而言的(就是没有添加动画的状态)。demo中从上到下有三个元素,分别应用了animation-fill-mode属性的三个值:backwards,forwards,both。结合前面对这三个属性值的说明,相信不难理解demo中三个元素的动画效果:
backwards和both使得第一个元素和第三个元素,在动画添加后都立即变为动画第一帧的状态。而第二个元素没有应用第一帧的状态。
forwards和both使得第二个元素和第三个元素,在动画结束后仍然保持动画最后一帧的状态。而第1个元素没有。
以上内容可能会让人觉得animation-fill-mode是一个比较简单的属性,因为它的作用非常的简单明了。尽管如此,我在最近做一些动画效果的时候却发现,这个属性在真正使用的时候要想完全融会贯通地去使用,还真不是那么容易,尤其是当我们需要同时应用多个动画,定义连续的复杂动画时,就可能会在写动画的过程中,碰到一些自己按理论不能理解清楚的点,虽然最后吧,我们总是能想办法搞定我们遇到的问题,那是因为这个属性毕竟只有那么几个值,多加调试当然能解决问题,但是做完了,心里面还是想解决那个为什么我之前那么写就不行的问题。所以本文从一些非常规的角度来研究animation-fill-mode在实际使用过程中可能会存在理解偏差的问题,我不敢保证在本文中,我提出的一些理解方式一定是正确的,只是以我现在的经验,只能得出这么些结论。希望本文可以抛砖引玉,发现一些更可靠更完美的思想。
首先,我想对animation-fill-mode的理论知识再做一次补充说明:
1)在animation-fill-mode的基础知识中,有这么几个关键词:动画等待时间(也叫动画延迟时间),动画结束后,第一帧,最后一帧。这些关键词的更深的含义是:
a. backwards一定是在动画延迟时间内才会生效;
b. forwards一定在动画完成之后才会生效,对于一个循环的动画来说,它没有动画完成后的状态,所以forwards不会起作用;
c. 第一帧和最后一帧不是绝对的,就是说第一帧不一定永远跟0%这帧对应,最后一帧不一定永远跟100%这帧对应。具体到底0%是第一帧还是100%是第一帧,跟另外两个动画属性有关系:animation-direction和 animation-iteration-count。举个例子:当animation-direction是alternate,animation-iteration-count是2的时候,第一帧和最后一帧就都是0%。至于为啥是这样,自己简单画个图就好理解了:
详细的规则在mdn上有完整地说明,所以这里不会再赘述了。这个规则并不存在理解偏差的问题,但是对于animation-fill-mode的第一帧跟最后一帧该如何判别还是比较重要的,所以有必要记录一下。
为了不增加以下内容的复杂性,剩下的内容都将以animation-direction为normal,animation-iteration-count为1这个前提来说明。接下来就来看看animation-fill-mode这个属性,还有哪些问题值得花点心思研究研究的。
1. 动画没有定义0%或100%的时候
假如我们动画里没有定义0%或100%,只定义了中间百分比的关键帧,animation-fill-mode会有什么样的表现呢?
先来观察アニメーションフィルモードに関するいくつかの考え:http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#アニメーションフィルモードに関するいくつかの考え
less源码:
<span style="color: #800000">#アニメーションフィルモードに関するいくつかの考え </span>{<span style="color: #ff0000"> .target.animate { animation-name</span>:<span style="color: #0000ff"> move_2</span>;<span style="color: #ff0000"> animation-duration</span>:<span style="color: #0000ff"> 2s</span>;<span style="color: #ff0000"> animation-delay</span>:<span style="color: #0000ff"> 1s</span>;<span style="color: #ff0000"> &.target_1 { animation-fill-mode</span>:<span style="color: #0000ff"> backwards</span>; }<span style="color: #800000"> &.target_2 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> forwards</span>; }<span style="color: #800000"> &.target_3 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> both</span>; }<span style="color: #800000"> } } @keyframes move_2 </span>{<span style="color: #ff0000"> 50% { transform</span>:<span style="color: #0000ff"> scale(1.2, 1.2)</span>; }<span style="color: #800000"> }</span>
このデモでは、異なるアニメーション塗りつぶしモードが適用された 3 つの要素が表示されますが、最終的な効果はまったく同じです。これは、アニメーションで 0% と 100% が定義されていないため、animation-fill-mode が必要な最初と最後のフレームを見つけることができないためです。上記のデモ アニメーションでは 50% がアニメーション定義に含まれていますが、一意性の理解によれば、50% のフレームは 1 つのフレームまたは最後のフレームと見なすことができます。 -mode はアニメーション定義の 0% と 100% のみを認識し、アニメーション定義の最初と最後のフレームは認識しません。
つまり、0% と 100% がなければ、animation-fill-mode は効果がないということですか?実際にはそうではありません。
アニメーション定義に 0% と 100% がない場合、アニメーションに開始フレームと終了フレームが存在しないことを意味するわけではありません。デフォルトでは、開始フレームと終了フレームが必要です。フレーム 対応するスタイルは、アニメーションが要素に追加される前のスタイルです。デフォルトの開始フレームと終了フレームの定義を 0% または 100% でオーバーライドできます。 言い換えれば、0% または 100% がない場合でも、animation-fill-mode は機能しますが、要素の初期状態を使用して機能するため、それを区別することはできません。
前の段落の結論は、w3c で導入されているのを見たわけではありませんが、私自身の考えや観察に基づいて推測しました。次に、私の判断を説明するために Chrome のアニメーション デバッグ ツールを使用します。後で複数のアニメーションでのアニメーション フィル モードの実践を紹介するときに、例を組み合わせてこれらの理論を使用して説明します。Chromeの新バージョンではアニメーションデバッグの機能が提供されています。起動方法は次のとおりです。
[アニメーション] タブが表示されると、以下のようなコンソールが表示され、タイムラインを制御してアニメーションをデバッグできます。
アニメーション コンソールが開くと、ページが読み込まれた後にページ内のアニメーション効果が監視されます。たとえば、アニメーションフィルモードに関するいくつかの考え のアニメーションの追加ボタンをクリックすると、コンソールは、アニメーションフィルモードに関するいくつかの考え で発生しているアニメーションを確認できます。
このアニメーション コンソールは、アニメーション タイムラインの調整、アニメーションの一時停止、アニメーションの速度制御、フレームごとの観察などの強力なアニメーション管理機能を実現できます。ただし、この記事ではその使い方については詳しく説明しません。仕事でたくさん使えます。ここで、このアニメーション コンソールのプレゼンテーションで、以前に作成した結論を説明したいと思います。
0% と 100% が定義されているかどうかに関係なく、アニメーションには開始フレームと終了フレームが必要です。 we は 0% と 100% で上書きできます。この記事のデモ 1 に戻り、ページを更新し、デモ 1 でアニメーションの追加ボタンをクリックして、表示されるアニメーション コンソールを観察しました。
アニメーションフィルモードに関するいくつかの考え のアニメーションには合計 3 つのキーフレーム定義が含まれているため、アニメーション コンソールでは、各要素のアニメーション タイムラインに最初のポイントと最後のポイントを含む 3 つのポイントが含まれていることがわかります。これらはすべて実線であることを意味します。はアニメーションの開始フレームと終了フレームで、中央のドットは中空であり、アニメーションの実行中のキーフレームであることを意味します。
アニメーションフィルモードに関するいくつかの考え をもう一度見てください。同じ方法でアニメーションを追加してから、コンソールを見てください:
对比アニメーションフィルモードに関するいくつかの考え的截图,可以发现,尽管アニメーションフィルモードに関するいくつかの考え中的动画只定义了1个50%的关键帧,但是在动画的时间轴上,依然出现了代表起始帧和结束帧的点,这也从一方面说明了,动画不管有没有0%和100%,起始帧和结束帧是一定存在的。
前面这个小结论,对于后面更复杂的一个实例的理解,比较关键,也是基于它,我才能得出后面更大的一个关于动画过程中属性冲突时优先级的猜想,所以这里花了不少的内容来介绍它。
接下来继续后面要探究的问题。
2. 动画作用过程中的样式与元素初始状态的样式冲突
在这个问题标题中,我用到了“动画作用过程”这个短语,而不是“动画过程”,是因为这两个的含义是不一样的。按照文首对动画阶段的划分,一个元素添加一个动画后,它就会经历三个阶段:动画等待,动画执行和动画结束。我们知道动画要做的事情,就是把动画定义里面的样式应用到元素上,而且我们可以确定的是动画执行阶段,动画定义的样式是一定会作用到元素之上的。那么在动画等待以及动画结束阶段呢,动画定义的样式是否也会作用到元素之上?这个就跟animation-fill-mode有关系了,如果该属性取forwards,那么动画结束阶段会受到动画结束帧定义的样式的作用;如果该属性取backwards,那么动画等待阶段,也会受到动画起始帧的作用;如果取both,那么动画结束跟动画等待阶段都会影响。换句话说:
如果animation-fill-mode取none,动画对一个的作用过程,简称之动画作用过程,就仅仅包括了动画执行阶段;
如果animation-fill-mode取backwards,动画作用过程就包含动画等待阶段跟动画执行阶段;
如果animation-fill-mode取forwards,动画作用过程就包含动画执行阶段跟动画结束阶段;
如果animation-fill-mode取both,动画作用过程就是整个添加动画之后的过程了。
以上提到的这个结论是对单个动画而言的,如果一个元素应有了多个动画,那么每个动画都会满足这个结论。
我们可以从动画控制台来直观感受下动画作用过程的不同类型。
这个结论,我也做了一个demo:http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#アニメーションフィルモードに関するいくつかの考え
less源码:
<span style="color: #800000">#アニメーションフィルモードに関するいくつかの考え </span>{<span style="color: #ff0000"> .target.animate { animation-name</span>:<span style="color: #0000ff"> move_3</span>;<span style="color: #ff0000"> animation-duration</span>:<span style="color: #0000ff"> 2s</span>;<span style="color: #ff0000"> animation-delay</span>:<span style="color: #0000ff"> 1s</span>;<span style="color: #ff0000"> &.target_1 { animation-fill-mode</span>:<span style="color: #0000ff"> none</span>; }<span style="color: #800000"> &.target_2 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> backwards</span>; }<span style="color: #800000"> &.target_3 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> forwards</span>; }<span style="color: #800000"> &.target_4 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> both</span>; }<span style="color: #800000"> } } @keyframes move_3 </span>{<span style="color: #ff0000"> 50% { transform</span>:<span style="color: #0000ff"> scale(1.2, 1.2)</span>; }<span style="color: #800000"> }</span>
不过这一块的目的不是为了说明这个demo的动画效果,而是为了介绍如何从动画控制台去看动画作用过程的范围:
从源码中可以看到:
.target_1应用了animation-fill-mode:none
.target_2应用了animation-fill-mode:backwards
.target_3应用了animation-fill-mode:forwards
.target_4应用了animation-fill-mode:none。
结合这个可以看出,动画控制台中,时间轴实心的部分就是动画的作用过程。
接下来回到本部分要研究问题主题,就是当元素在动画作用过程中的时候,动画定义的属性与元素初始的属性冲突时会有什么表现。
先看这个demo:http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#demo4
(动画内容较多,所以没做gif,可以去上面的链接中查看)
less源码:
<span style="color: #800000">#demo4 </span>{<span style="color: #ff0000"> .target { transform</span>:<span style="color: #0000ff"> scale(1.2, 1.2)</span>; }<span style="color: #800000"> .target.animate </span>{<span style="color: #ff0000"> animation-duration</span>:<span style="color: #0000ff"> 2s</span>;<span style="color: #ff0000"> animation-delay</span>:<span style="color: #0000ff"> 1s</span>;<span style="color: #ff0000"> &.target_1 { animation-fill-mode</span>:<span style="color: #0000ff"> none</span>;<span style="color: #ff0000"> animation-name</span>:<span style="color: #0000ff"> move_4_01</span>; }<span style="color: #800000"> &.target_2 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> backwards</span>;<span style="color: #ff0000"> animation-name</span>:<span style="color: #0000ff"> move_4_01</span>; }<span style="color: #800000"> &.target_3 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> forwards</span>;<span style="color: #ff0000"> animation-name</span>:<span style="color: #0000ff"> move_4_01</span>; }<span style="color: #800000"> &.target_1_02 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> none</span>;<span style="color: #ff0000"> animation-name</span>:<span style="color: #0000ff"> move_4_02</span>; }<span style="color: #800000"> &.target_2_02 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> backwards</span>;<span style="color: #ff0000"> animation-name</span>:<span style="color: #0000ff"> move_4_02</span>; }<span style="color: #800000"> &.target_3_02 </span>{<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> forwards</span>;<span style="color: #ff0000"> animation-name</span>:<span style="color: #0000ff"> move_4_02</span>; }<span style="color: #800000"> } } @keyframes move_4_01 </span>{<span style="color: #ff0000"> 0% { transform</span>:<span style="color: #0000ff"> translate(-50px, 0)</span>; }<span style="color: #800000"> 50% </span>{<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(0, 0)</span>; }<span style="color: #800000"> 100% </span>{<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(50px, 0)</span>; }<span style="color: #800000"> } @keyframes move_4_02 </span>{<span style="color: #ff0000"> 0% { transform</span>:<span style="color: #0000ff"> translate(-50px, 0) scale(1.2, 1.2)</span>; }<span style="color: #800000"> 50% </span>{<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(0, 0) scale(1.2, 1.2)</span>; }<span style="color: #800000"> 100% </span>{<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(50px, 0) scale(1.2, 1.2)</span>; }<span style="color: #800000"> }</span>
在上面的截图中,我用箭头把元素跟动画控制台中的动画元素时间轴做了一个对应关系,方便理解。
在这个demo里面,元素默认都有一个transform: scale(1.2,1.2)的设置,然后定义两个动画,move_4_01这个动画的样式定义里面同样包含了一个transform属性,而且没有保留元素默认的transform设置。move_4_02这个动画的样式定义里面也包含了一个transform的设置,跟move_4_01不同的是,这个动画还保留了元素默认的scale(1.2,1.2)的设置。
demo中用到了六个元素,它们按照animation-fill-mode分成了三组,以便对应不同的动画作用过程;每组里面的两个元素,分别应用move_4_01和move_4_02两个动画。
通过在时间轴上的动画等待阶段,动画执行阶段和动画结束阶段,任取三个时间点,观察元素的表现,可以帮助分析在动画作用过程中,当动画属性与初始属性冲突时存在的规律:
动画等待阶段:
动画执行阶段:
动画结束阶段:
考虑到篇幅的原因,这里就不再详细的分析以上各个截图的现象了。我最终得出的结论是:在动画属性与初始属性冲突的时候,只要一个元素处于动画作用过程中,就会启用动画定义的属性,覆盖元素初始化的属性。而前面的结论告诉我们,animation-fill-mode可以改变元素的动画作用过程,所以明白这点,对于做动画的状态分析会比较有帮助。
继续下一个问题。
3. 一个元素应用多个动画时,多个动画定义的属性冲突
当一个元素应用了多个动画时,假如动画定义的属性有冲突,也就是说多个动画都用到了同一个属性,这种冲突该怎么去分析呢?
先来看下一个アニメーションフィルモードに関するいくつかの考え:http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#アニメーションフィルモードに関するいくつかの考え
less源码:
<span style="color: #800000">#アニメーションフィルモードに関するいくつかの考え </span>{<span style="color: #ff0000"> .target.animate { animation-duration</span>:<span style="color: #0000ff"> 1s, 1s</span>;<span style="color: #ff0000"> animation-delay</span>:<span style="color: #0000ff"> 1s, 2s</span>;<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> both</span>;<span style="color: #ff0000"> &.target_1 { animation-name</span>:<span style="color: #0000ff"> move_5, bg_change_5</span>; }<span style="color: #800000"> &.target_2 </span>{<span style="color: #ff0000"> animation-name</span>:<span style="color: #0000ff"> bg_change_5, move_5</span>; }<span style="color: #800000"> } } @keyframes move_5 </span>{<span style="color: #ff0000"> 0% { transform</span>:<span style="color: #0000ff"> translate(-50px, 0)</span>; }<span style="color: #800000"> 50% </span>{<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(0, 0)</span>; }<span style="color: #800000"> 100% </span>{<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(50px, 0)</span>; }<span style="color: #800000"> } @keyframes bg_change_5 </span>{<span style="color: #ff0000"> 0% { background-color</span>:<span style="color: #0000ff"> orange</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> scale(0.8)</span>; }<span style="color: #800000"> 100% </span>{<span style="color: #ff0000"> background-color</span>:<span style="color: #0000ff"> red</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> scale(1.2)</span>; }<span style="color: #800000"> }</span>
このデモでは、2 つのアニメーションが定義されています。move_5 は x 軸上の要素のオフセットを変更し、bg_change_5 は要素のスケールと背景色を同時に変更します。どちらの要素にも、これら 2 つのアニメーションが同時に適用されます。適用の順序を除き、遅延、継続時間、アニメーションフィルモードなどの他のパラメーターはまったく同じです。アニメーション コンソールに表示されるタイムラインと組み合わせて、アニメーション プロセス中のこれら 2 つの要素のルールを見てみましょう。
アニメーション待機ステージを例に挙げます:
この段階では、両方の要素の背景がオレンジ色で、.target_2 の背景はオレンジ色ですが、サイズは変更されていません。少し左にあります。上記のソース コードから、背景の色とサイズに影響を与えるアニメーションは bg_change_5 である必要があり、要素の X 軸のオフセットに影響を与えるアニメーションは move_5 である必要があることがわかります。どちらの要素にも 2 つのアニメーションが同時に適用されており、遅延、継続時間、アニメーションフィルモードは同じですが、パフォーマンス ステータスはまったく同じではありません。 それらの唯一の違いはアニメーションを適用する順序です、.target_1 のアニメーションの順序は、move_5、bg_change_5 です。 .target_2 のアニメーション シーケンスは bg_change_5、move_5 です。したがって、この現象の最終的な合理的な説明は次のようになります:
.target_1 bg_change_5 アニメーションが最後に来るため、bg_change_5 の最初のフレームのtransform:scale(0.8)がtransform:translate(-50px,0);
をカバーします。.target_2 は、move_5 が後に来るため、move_5 のtransform: translation(-50px,0) がtransform:scale(0.8)をカバーします
つまり、複数のアニメーションのプロパティが競合する場合、後で適用されるアニメーションの優先度が、最初に適用されるアニメーションの優先度よりも高くなります。しかし、この結論は厳密なものではないことに注意してください。
この結論は 250 ミリ秒の瞬間に基づいているため、複数のアニメーションが適用されている可能性がある要素では、時点が異なります。つまり、各アニメーションが異なるアニメーション ステージにある可能性があり、一部はまだアニメーション ステージにある可能性があります。待機ステージでは、次のように、実行ステージにあるものと、すでに完了ステージにあるものがあります。
前の結論が真実かどうかを証明するには、タイムライン上でより多くの時間をかけて検証する必要があります。しかし、最終的には、スペースの都合上、分析用にスクリーンショットを撮るタイミングをこれ以上見つけることができなかったので、前にも言った通りの結論に達しました いくつかのテストで、それらはすべて客観的に確立された結論です。
ただ、前の結論の説明では十分に単純明快ではありません。以下にもっと簡単に説明します。まずはこの写真を見てみましょう:
この図は要素を説明しています。複数のアニメーションを同時に適用すると、アニメーション コンソールで各アニメーションのタイムラインを確認できます。画像から次の情報を引き出すことができます:
アニメーションの適用順序はanimate_1、animate_2、animate_3です
animate_1の遅延時間はt4(t4から1/5の位置)-t1、アニメーション終了時間はt8
animate_2の遅延時間は0、アニメーション終了時間はt5です
animate_3の遅延時間はt3-t1、アニメーションの終了時間はt7です
この画像では、すべてのアニメーションのアニメーションフィルモードが両方に設定されていると仮定します。これは、画像内のすべてのタイムラインの実線部分がアニメーションのアクションプロセスを表すことを意味します。次に、タイムライン上の任意の瞬間を選択します。 , この時点で複数のアニメーションに属性の競合がある場合、属性の優先順位はアニメーションが適用される順序によって完全に決定されます:
。有了这个结论,将来在分析一些多动画效果的时候就会比较好下手了。我们只要先确定好单个动画的作用过程,然后找到我们需要分析的动画时间轴的点,最后再从上往下找到最后一个包含冲突属性的动画轴即可。
另外,从这部分的问题,我还想说明另外一个结论,这个结论比较好理解,也没太多要去分析的,就是应用多动画的时候,各个动画之间都是独立的,所以动画的那些属性,如animation-delay, animation-fill-mode不会受其它动画的影响。这个从动画控制台各个动画独立的时间轴也能看出来。为什么会有这个结论呢,是因为在我没有去研究到这些规律之前,我以为动画的animation-fill-mode可能会受多个动画的animation-delay的影响,就拿前面的demo来说,元素在应用动画时,第一个动画延迟1s,第二个动画延迟2s,我初以为第二个动画的animation-fill-mode会在第一个动画的延迟结束之后才会生效,不然这两个动画如果同时应用animation-fill-mode的话,属性冲突该怎么解决?最后有了前面两个重要的结论,我原来的那个认识也就很好解释了。
接下来看一个简单实际的多动画的例子,来看看多动画的效果如果碰到问题该怎么分析。
4. 实例分析
这个演示的效果实例是,元素默认是隐藏的,当添加动画后,元素以淡入的方式从x轴向左偏移-50px的位置,移动到原位置,显示1s之后,再从原位置以淡出的方式,移动到x轴往右偏移50px的位置。正确的效果如下:
一开始我的做法是这样的:http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#アニメーションフィルモードに関するいくつかの考え
<span style="color: #800000">#アニメーションフィルモードに関するいくつかの考え </span>{<span style="color: #ff0000"> .target</span>:<span style="color: #0000ff">not(.target_1) { visibility: hidden</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 0</span>; }<span style="color: #800000"> .target.animate </span>{<span style="color: #ff0000"> &.target_2 { animation-name</span>:<span style="color: #0000ff"> move_6_01, move_6_02</span>;<span style="color: #ff0000"> animation-duration</span>:<span style="color: #0000ff"> 1s, 1s</span>;<span style="color: #ff0000"> animation-delay</span>:<span style="color: #0000ff"> 0s, 2s</span>;<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> both</span>; }<span style="color: #800000"> } } @keyframes move_6_01 </span>{<span style="color: #ff0000"> 0% { visibility</span>:<span style="color: #0000ff"> hidden</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 0</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(-50px, 0)</span>; }<span style="color: #800000"> 100% </span>{<span style="color: #ff0000"> visibility</span>:<span style="color: #0000ff"> visible</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 1</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(0, 0)</span>; }<span style="color: #800000"> } @keyframes move_6_02 </span>{<span style="color: #ff0000"> 100% { visibility</span>:<span style="color: #0000ff"> hidden</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 0</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(50px, 0)</span>; }<span style="color: #800000"> }</span>
正如你所看到的,我定义了两个动画move_6_01,move_6_02,这两个动画按照01 02 的顺序应用到.target_2这个元素上,两个动画持续时间都是1s,第一个动画延迟时间为0,第二个动画延迟时间为2s,以便达到淡入淡出的时间都为1s,然后中间停留的时间也是1s的效果;两个动画同时应用了animation-fill-mode:both。然后还给.target_2这个元素设置了初始的属性:visibility: hidden,opactity: 0。.target_1只是一个对比的元素,没有添加动画效果。
当我运行这个代码的时候最后却发现,一点动画效果都没有,动画控制台已经监听到动画了,但是元素看不见动画效果:
我以为是animation-fill-mode的原因,所以我在上面的demo基础上,将animation-fill-mode稍加调整,改为both,forwards,也就是第二个动画不启用backwards的效果:http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#アニメーションフィルモードに関するいくつかの考え
这个时候效果变成:
代码:
<span style="color: #800000">#アニメーションフィルモードに関するいくつかの考え </span>{<span style="color: #ff0000"> .target</span>:<span style="color: #0000ff">not(.target_1) { visibility: hidden</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 0</span>; }<span style="color: #800000"> .target.animate </span>{<span style="color: #ff0000"> &.target_2 { animation-name</span>:<span style="color: #0000ff"> move_6_01, move_6_02</span>;<span style="color: #ff0000"> animation-duration</span>:<span style="color: #0000ff"> 1s, 1s</span>;<span style="color: #ff0000"> animation-delay</span>:<span style="color: #0000ff"> 0s, 2s</span>;<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> both,forwards</span>; }<span style="color: #800000"> } }</span>
在这一步,淡入跟停留的效果出来了,可是淡出的效果没有出来。
虽然最后,我在不明白这其中的原理的前提下,将动画调试出来了,但是对于这个问题还是觉得很有必要去深入研究一下,这也是我写本文的初衷。有了之前的那些结论,接下来就看看如何分析前面两步的现象产生的原因。
先来看看アニメーションフィルモードに関するいくつかの考え(就是本部分的第一个)的动画时间轴:
前面说过,动画是独立的,动画时间轴的实心部分表示动画作用过程,多动画的时候,在动画控制台中,可以根据从上往下的顺序判断属性的优先级。观察上面的截图发现:在动画添加后,两个动画的作用过程都是相同的,而由于move_6_02这个动画后应用,所以move_6_02这个动画,在有属性冲突的时候,优先级始终是高的那一个。
那么为什么在添加动画后,什么动画效果都看不到呢?这个原因在于move_6_02这个动画只定义了100%这一帧,没有定义0%,那就意味着move_6_02这个动画的起始帧会用元素默认的属性定义来代替。而元素的默认属性中有两个属性会导致元素在动画过程的0-2s都不会显示,就是visibility: hidden,opactity: 0这两个属性。
我一开始的理解是,move_6_01这个动画的100%这一帧,会让元素显示出来(visibility: visible,opactity: 1),所以move_6_02只用定义100%这一帧即可。但是动画是独立的,move_6_02这个动画的作用不会跟其它动画有关联,所以以上做法无法实现需要的效果。
再来看アニメーションフィルモードに関するいくつかの考え:
在アニメーションフィルモードに関するいくつかの考え里面,animation-fill-mode调整为both,forwards,改变了两个动画的作用过程,解决了move_6_02优先级高导致move_6_01的效果看不进的问题,但是为什么アニメーションフィルモードに関するいくつかの考え在2s之后没有出现淡出的效果呢?
这个还是跟move_6_02这个动画没有定义0%这一帧有关系。当动画没有定义0%的时候,就会用默认的属性来作为起始帧。而元素的默认属性是
visibility: hidden,opactity: 0,move_6_02的100%里面定义的属性也是visibility: hidden,opactity: 0,也就是说这个动画实际上不会对元素的可见性做任何的改变,其实偏移还是有的,只是看不见而已。
所以最好解决这个问题,只要在アニメーションフィルモードに関するいくつかの考え的基础上,给move_6_02加一个0%的定义即可:
http://liuyunzhuge.github.io/blog/animation/dist/html/animation-fill-mode.html#demo8
<span style="color: #800000">#demo8 </span>{<span style="color: #ff0000"> .target</span>:<span style="color: #0000ff">not(.target_1) { visibility: hidden</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 0</span>; }<span style="color: #800000"> .target.animate </span>{<span style="color: #ff0000"> &.target_2 { animation-name</span>:<span style="color: #0000ff"> move_8_01, move_8_02</span>;<span style="color: #ff0000"> animation-duration</span>:<span style="color: #0000ff"> 1s, 1s</span>;<span style="color: #ff0000"> animation-delay</span>:<span style="color: #0000ff"> 0s, 2s</span>;<span style="color: #ff0000"> animation-fill-mode</span>:<span style="color: #0000ff"> both,forwards</span>; }<span style="color: #800000"> } } @keyframes move_8_01 </span>{<span style="color: #ff0000"> 0% { visibility</span>:<span style="color: #0000ff"> hidden</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 0</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(-50px, 0)</span>; }<span style="color: #800000"> 100% </span>{<span style="color: #ff0000"> visibility</span>:<span style="color: #0000ff"> visible</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 1</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(0, 0)</span>; }<span style="color: #800000"> } @keyframes move_8_02 </span>{<span style="color: #ff0000"> 0% { visibility</span>:<span style="color: #0000ff"> visible</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 1</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(0, 0)</span>; }<span style="color: #800000"> 100% </span>{<span style="color: #ff0000"> visibility</span>:<span style="color: #0000ff"> hidden</span>;<span style="color: #ff0000"> opacity</span>:<span style="color: #0000ff"> 0</span>;<span style="color: #ff0000"> transform</span>:<span style="color: #0000ff"> translate(50px, 0)</span>; }<span style="color: #800000"> }</span>
この例を通して、この記事でまとめたいくつかの理論の実践的な方法を皆さんに理解していただければ幸いです。
この記事で提案した結論の一部を少し改良して、将来複雑なアニメーション エフェクトを作成する際に役立つことを願っています。
1. アニメーションは独立しており、それぞれが独自のタイムラインを持ち、互いに影響しません。2. anime-fill-mode はアニメーション定義の 0% と 100% のみを認識し、アニメーション定義の最初と最後のフレームは認識しません。
3. アニメーション定義に 0% と 100% がない場合、アニメーションには開始フレームと終了フレームが必要です。デフォルトでは、開始フレームと終了フレームに対応するスタイルは、アニメーションが追加される前の要素のスタイルです。デフォルトの開始フレームと終了フレームの定義を 0% または 100% でオーバーライドできます。 anime-fill-mode が実際に適用するのは、アニメーションの開始フレームと終了フレームです。
4. アニメーション コンソールでは、タイムラインの実線部分がアニメーション プロセスです。アニメーション プロパティが初期プロパティと競合する場合、要素がアニメーションの処理中である限り、アニメーションで定義されているプロパティの優先順位は常に要素の初期プロパティよりも高くなります。
5. マルチアニメーションエフェクトでは、いつでもどのアニメーションの優先度が高いかを判断するには、アニメーションコンソールでその瞬間に対応する線を見つけ、その線とすべてのアニメーションの実線部分(アニメーションアクション)の交点を見つけます。プロセス)に従って、上から下の順に、より下にあるポイントが優先されます。
読んでいただきありがとうございます。