原文: Moving across a Curved path in CSS withlayered anime
翻訳: Tuya Code Dragon
翻訳者注記: いくつかのコード例は原文で見ることができます (著者がブログ投稿に書いています...) が、Gif にするのが面倒でした。
CSS アニメーションとトランジションは、点 A から点 B への直線的な動きの実現に適しており、動きの軌跡は直線のパスになります。要素にアニメーションまたはトランジションを追加した後、ベジェ曲線をどのように調整しても、円弧パスに沿って移動させることはできません。タイミング関数属性をカスタマイズすることでバウンス効果を作成できますが、X 軸と Y 軸に沿った相対的な動きは常に同じになります。
JavaScript を使用して自然な動きを実現する代わりに、アニメーションを階層化して既存の制限を回避するというシンプルなアプローチを試してください。 2 つ以上の要素をアニメーション化すると、X 軸に沿った移動に 1 つのタイミング関数を使用し、Y 軸に沿った移動に別のタイミング関数を使用して、要素のパスをよりきめ細かく制御できます。
解決策に入る前に、何が問題なのかを見てみましょう。 CSS アニメーションとトランジションでは、直線的なパスに制限されます。要素は常に、点 A から点 B までの最短パスに沿って移動します。別の方法を見つけて、「最短パス」ではなく「より良いパス」に沿って移動するように CSS に指示したらどうなるでしょうか?
CSS (ハードウェア アクセラレーションを有効にする) を使用して 2 点間の移動を実現する最も簡単な方法は、Transform の Translation を使用して一定時間内に要素を移動することです。これにより直線運動が生成されます。 @keyframes では、(0,0) と (100,-100) の間を行き来するつもりです。上の例を参照してください:
@keyframes straightLine { 50% { transform: translate3D(100px, -100px, 0); }}.dot { animation: straightLine 2.5s infinite linear;}
これらを理解するのは難しくないようですが、少し待って、必要な解決策と分割アニメーションが視覚的にどのように見えるかについて考えてみましょう。
0% では、要素は (0,0) から始まり、50% では、translate3D(100px, -100px, 0) を使用して (100,-100) に移動し、その後、元に戻ります。元のパス。つまり、要素を右に 100 ピクセル、上に 100 ピクセル移動し、2 つの方向を組み合わせて要素を斜めに移動しました。
では、最初に示した例で円弧パスを実装するにはどうすればよいでしょうか?直線ではないパスを作成するには、 X 軸と Y 軸に沿った要素の移動速度を非同期にする必要があります 。
前の例では線形直線運動関数を使用しました。移動する要素の周囲にコンテナーをラップすると、1 つのアニメーション関数を X 軸に適用し、もう 1 つを Y 軸に適用できます。次の例では、X 軸でイーズイン、Y 軸でイーズアウトを使用します。
残念ながら、変換アニメーションを単にオーバーレイすることはできません。最後に宣言されたアニメーションのみが実行されます。では、2 つのアニメーション効果を組み合わせるにはどうすればよいでしょうか?別の要素の中に要素を配置したり、コンテナ要素に 1 つのアニメーションを追加したり、内部の子要素に別のアニメーションを追加したりできます。
上の例では、コンテナ要素が完全に透明であることを除いて、円弧パスに沿って移動する点と 2 つの独立した要素が一緒にアニメーション化されていることがわかりました。 2 つの要素が円弧パスに沿ってどのように相互作用するかを明確に確認するために、コンテナ要素に境界線を追加しましょう。
点は境界線付きのボックス内に隠れています。内部的には、点は境界線に沿って移動します。ボックスと一緒に X 軸が動き、同時に Y 軸方向に上下に移動します。コンテナ ボックスの境界線を削除すると、円弧のパスが得られます。 HTML で 2 つの要素を使用する代わりに、疑似要素を使用することをお勧めします。 HTML が次のような場合:
<div class="dot"></div>
疑似要素を追加できます:
.dot { /* 容器:沿 X 轴运动 */}.dot::after { /* 黑点儿,沿 Y 轴运动 */}
次に、2 つの独立したアニメーション コードが必要になります。1 つは X 軸用、もう 1 つは Y 軸用です。 easy-in は 1 つの場所で使用され、ease-out は別の場所で使用されることに注意してください。
.dot { /*省略 一些布局代码...*/ animation: xAxis 2.5s infinite ease-in;}.dot::after { /* 渲染小黑点儿*/ animation: yAxis 2.5s infinite ease-out;}@keyframes xAxis { 50% { animation-timing-function: ease-in; transform: translateX(100px); }}@keyframes yAxis { 50% { animation-timing-function: ease-out; transform: translateY(-100px); }}
WebKit プレフィックスを追加し、いくつかのカスタム シェルを使用します。イーズインとイーズアウトをサール曲線に置き換えると、記事の冒頭で示した効果を実現できます。
.demo-dot { -webkit-animation: xAxis 2.5s infinite cubic-bezier(0.02, 0.01, 0.21, 1); animation: xAxis 2.5s infinite cubic-bezier(0.02, 0.01, 0.21, 1);}.demo-dot::after { content: ''; display: block; width: 20px; height: 20px; border-radius: 20px; background-color: #fff; -webkit-animation: yAxis 2.5s infinite cubic-bezier(0.3, 0.27, 0.07, 1.64); animation: yAxis 2.5s infinite cubic-bezier(0.3, 0.27, 0.07, 1.64);}@-webkit-keyframes yAxis { 50% { -webkit-animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1); animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1); -webkit-transform: translateY(-100px); transform: translateY(-100px); }}@keyframes yAxis { 50% { -webkit-animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1); animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1); -webkit-transform: translateY(-100px); transform: translateY(-100px); }}@-webkit-keyframes xAxis { 50% { -webkit-animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64); animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64); -webkit-transform: translateX(100px); transform: translateX(100px); }}@keyframes xAxis { 50% { -webkit-animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64); animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64); -webkit-transform: translateX(100px); transform: translateX(100px); }}
以下は記事の冒頭 例:
jsbin.com の JS Bin
すべての例で @keyframes を使用していることに気づくかもしれませんが、これは単に、次の 2 つの方法を示したいためです。黒点往復状態。 A 点から B 点への動きだけを実現したい場合は、レイヤーアニメーションのトランジション属性を使用することも簡単です。
絶対的に配置された要素がある場合、左と下の属性に特殊効果を追加することで円弧パスの移動を実現できます。単一の要素で十分であり、コンテナ要素は必要ありません。これを実行しない理由は、パフォーマンスが若干低下し、アニメーションのすべてのフレームで再描画が発生するためです。疑似要素を含むレイヤー化アニメーションと、translate 属性で有効になっているハードウェア アクセラレーションを使用すると、アニメーション効果が向上し、パフォーマンスが向上します。
翻訳者自身が絶対配置の例を作成しました:
jsbin.com の JS Bin