数週間前、Twitter のほぼ全員が星をハートに変えていることに気づきました。間違いなく、これは大きな議論のトピックの 1 つです...しかし、私が心配しているのは...このアニメーションは (単一の画像や SVG ではなく) CSS だけを使用して実現できるのでしょうか?
それが重要ではないことはわかっていますが、このアイデアを思いついたとき、実行可能な解決策を思いつくまで文字通り眠れませんでした。
いくつかの実験を経て、ついに答えが見つかりました。結果は完璧ではありませんが (SCSS/CSS が多く、約 400 行)、満足のいくものです (少なくとも私の予想に基づくと)。
では、私が行った手順を説明します。
まず、センター (.heart)、ハロー (.ring)、サークル (.circles) の 3 つのレイヤーに分解し、最後にそれらをコンテナー (.heart-wrapper) にまとめます。次に、各レイヤーを作成し、アニメーションを付けて、最後にそれらを結合しました。
最初の部分は中心部分 ( .heart ) です。
中央領域全体を 4 つの長方形に分割しました。
各長方形領域に疑似要素 ( :after ) を使用し、 border-radius 要素を使用して、各パーツをできるだけ元の形状に近づけます。
その後、color 属性と overflow:hidden 属性を使用しました。
2 番目の部分はハロー部分 (.ring) です。
これは、異なる境界線のサイズと幅/高さの値を使用した単純な円要素です。
3 番目の部分はサークル ( .circles ) です。
この部分を作成するときは、中央の部分に透明な丸い要素を使用し、ボックスの影を追加しました。
各円でカンマ区切りのシャドウボックス属性を使用します。x / y 位置は Compass を使用します。 sin / cos を使用します。 計算された角度の値。
sin() および cos() に関連する関数については、多くの数学関連関数をカバーする Sassy Math ライブラリを使用できます。
この部分はそれほど複雑ではありません。
メイン要素の幅/高さの属性値を(設定位置の左/上に応じて)増減します。決定する必要がある唯一のことは、内部の要素がこの要素に適合するかどうかです。
枠線のサイズ、内側のリングのサイズと位置を調整し、色の設定にも注意してください。
この部分は少し注意が必要です。なぜなら、すべての境界影は時間の経過とともに変化し続け (X/Y 位置、サイズ、色)、そのうちの 1 つだけが変化するからです。カンマ区切り値属性を使用しました。
例:
51.85185% { box-shadow: -8.48528em -8.48528em 0 -0.83333em #a068ce, -8.38671em -5.44639em 0 -0.83333em #b752e1, 1.34357em -11.92455em 0 -0.83333em #99e9c8, -0.97087em -9.95276em 0 -0.83333em #bae3d7, 10.16069em -6.38438em 0 -0.83333em #d3f491, 7.17606em -6.9645em 0 -0.83333em #dce483, 11.3266em 3.96335em 0 -0.83333em #59c392, 9.91926em 1.26817em 0 -0.83333em #67cd9f, 3.96335em 11.3266em 0 -0.83333em #caadc7, 5.19306em 8.54588em 0 -0.83333em #959ff3, -6.38438em 10.16069em 0 -0.83333em #ca5ed8, -3.44362em 9.38837em 0 -0.83333em #a975d1, -11.92455em 1.34357em 0 -0.83333em #c35dd1, -9.48718em 3.16122em 0 -0.83333em #90e0be;}
これは 1 つのステップにすぎません...
読みやすく、調整しやすいように、この問題を処理する Sass 関数を作成しました。 :
@function setBoxShadow($distance1, $distance2, $size1, $size2, $shiftAngle, $colorRatio) { $boxS: (); @for $i from 1 through length($circles) { $circle: nth($circles, $i); $order: $i - 1; $angle1: ($order * $angleBetweenCircles) + $shiftAngleBeginning; $angle2: $angle1 + $shiftAngle; $distanceRatio1: $size * $distance1; $distanceRatio2: $size * $distance2; $firstCircle: map-get($circle, first); $firstCircleStart: map-get($firstCircle, start); $firstCircleEnd: map-get($firstCircle, end); $secondCircle: map-get($circle, second); $secondCircleStart: map-get($secondCircle, start); $secondCircleEnd: map-get($secondCircle, end); $boxS: append($boxS, cos($angle1) * $distanceRatio1 sin($angle1) * $distanceRatio1 0 $circleSize * $size1 mix($firstCircleStart, $firstCircleEnd, $colorRatio) ); $boxS: append($boxS, cos($angle2) * $distanceRatio2 sin($angle2) * $distanceRatio2 0 $circleSize * $size2 mix($secondCircleStart, $secondCircleEnd, $colorRatio) ); } @return join($boxS, (), "comma");}
この関数は、すべての円 (Sass Map に保存されている) を反復処理し、それに応じて box-shadow プロパティ値 (大きな円と小さな円) をペアで設定します。距離の大きさに基づいて、パラメータを渡して、それらの間のサイズ、色、角度を変更します。
次に、@ が書いた https://medium.com/@chrismabry/how-did-they-do-that-the-twitter-like-animation- をベースにしました。 chrismabry- 2a473b658e43 この記事は時間/パーセンテージによってアニメーション化されています。
そこで、28 のステップに分割しました
$animStep: 100% / 27;
実行には 0.8 秒かかりました
$animDuration: 0.8s;
関数を使用して各ステップのパーセンテージを生成しました:
@function setStep($n) { @return ($n — 1) * $animStep }
例:
#{setStep(6)}
出力は次のようになります:
18.51852%
これで、3 つの部分をマージできます。
この下の図は、私の長い説明よりも優先されます:
この時点で、コンテナー ( . active ) にクラスを追加/削除することによって、アニメーションがアクティブ化/一時停止されます。私の例では、クリックすることでクラスを切り替えています。
私は目標を達成しましたが、自己挑戦を完了しただけで他には何もないと思われるかもしれません。
この例の実装の大部分は CSS3 アニメーション http://caniuse.com/#feat=css-animation に基づいているため、ブラウザーでサポートされている現在のバージョンは現在のバージョン (IE10+) です。
効果はおおよそ次のとおりです。
コードを可能な限り簡潔かつ整然と保ち、テストや変更を容易にするために先頭に Sass 変数を設定しました。もっと良いアイデアがある場合は、お知らせください (JS で debug を true に設定すると、アニメーションを段階的に見ることができます)。
この記事は @Nicolas Escoffier 氏の「Twitter のハート アニメーションをフル CSS で」をもとに翻訳したものです。翻訳内容が不十分な場合や、間違っている点がある場合は、お友達に質問してください。業界にアドバイスを求めます。この翻訳を転載したい場合は、英語の出典を明記してください: https://blog.prototypr.io/twitter-s-heart-animation-in-full-css-b1c00ca5b774#.p31ds62ns。
現役学生、コンピューターサイエンスを専攻する学部生。積極的で笑いが大好きな女の子。フロントエンドが大好きで、他の人とコミュニケーションしたり共有したりするのが好きです。自分の心の中の自分を自分の努力で実現したいと思っています。 Weibo: @京-如秋叶