CSS 無限および円形回転画像スライダー

ソースノード: 1765846

画像スライダー (カルーセルとも呼ばれます) はどこにでもあります。 がある 共通のスライダーを作成するための多くの CSS トリック 画像が左から右 (またはその逆) にスライドする場所。 と同じ扱いです そこにある多くのJavaScriptライブラリ 複雑なアニメーションで派手なスライダーを作成します。 この投稿では、そのようなことは行いません。

ちょっとした一連の記事を通して、おしゃれで珍しい CSS のみのスライダーを探っていきます。 同じ昔ながらのスライダーに飽き飽きしているなら、あなたは正しい場所にいます!

CSSスライダーシリーズ

この最初の記事では、私が「円形回転画像スライダー」と呼んでいるものから始めます。

かっこいいでしょ? コードを分析しましょう!

HTMLマークアップ

あなたが私の一連の ファンシーな画像装飾 or CSS グリッドとカスタム形状の場合、私の最初のルールは可能な限り最小の HTML で作業することです。 私はコードをたくさん詰め込む前に、CSS の解決策を見つけようと常に努力しています。

sおよびその他のもの。

ここでも同じルールが適用されます — コードはコンテナー内の画像のリストに過ぎません。

XNUMX つの画像で作業しているとしましょう。

それでおしまい! それでは、コードの興味深い部分に移りましょう。 しかし、最初に、スライダーがどのように機能するかのロジックを理解するために、これに飛び込みます。

システムを教えてください。

削除した動画はこちら overflow: hidden 画像がどのように動いているかをよりよく理解できるように、CSS から:

XNUMX つの画像が、反時計回りに回転する大きな円の上に配置されているようなものです。

すべての画像は同じサイズです ( S 図中)。 すべての画像の中心と交差し、半径を持つ円である青い円に注意してください (R)。 この値は、後でアニメーションに必要になります。 R 等しい 0.707 * S. (その方程式を与える幾何学は飛ばします。)

CSSを書いてみよう!

使用します CSSグリッド すべての画像を同じ領域に配置するには、次のようにします。

.gallery  {
  --s: 280px; /* control the size */

  display: grid;
  width: var(--s);
  aspect-ratio: 1;
  padding: calc(var(--s) / 20); /* we will see the utility of this later */
  border-radius: 50%;
}
.gallery > img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}

これまでのところ、それほど複雑なことはありません。 トリッキーな部分はアニメーションです。

大きな円を回転させることについて話しましたが、実際には、各画像を個別に回転させて、大きな回転する円の錯覚を作成します。 では、アニメーションを定義しましょう。 m、画像要素に適用します。

.gallery > img {
  /* same as before */
  animation: m 8s infinite linear;
  transform-origin: 50% 120.7%;
}

@keyframes m {
  100% { transform: rotate(-360deg); }
}

主なトリックは、その強調表示された行に依存しています。 デフォルトでは、CSS transform-origin プロパティは次と等しい center (または 50% 50%) これにより、画像が中心を中心に回転しますが、その必要はありません。 画像を中心を中心に回転させる必要があります 大きな円 画像が含まれているため、新しい値 transform-origin.

Rが等しいので 0.707 * S、私たちはそれを言うことができます R 等しい 70.7% 画像サイズの。 これは、どのように取得したかを示す図です。 120.7% 値:

アニメーションを実行して、何が起こるか見てみましょう。

分かってる。 結果は私たちが望んでいたものとはかけ離れていますが、実際には非常に近いものです。 画像が XNUMX つだけのように見えるかもしれませんが、すべての画像を重ね合わせていることを忘れないでください。 それらはすべて同時に回転しており、上部の画像のみが表示されます。 この重複を避けるために、各画像のアニメーションを遅らせる必要があります。

.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 8s / 4 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 8s / 4 */
.gallery > img:nth-child(4) { animation-delay: -6s; } /* -3 * 8s / 4 */

物事はすでに良くなっています!

コンテナーのオーバーフローを非表示にすると、既にスライダーが表示されていますが、アニメーションを少し更新して、各画像が移動する前に短時間表示されるようにします。

それを行うために、アニメーション キーフレームを更新します。

@keyframes m {
  0%, 3% { transform: rotate(0); }
  22%, 27% { transform: rotate(-90deg); }
  47%, 52% { transform: rotate(-180deg); }
  72%, 77% { transform: rotate(-270deg); }
  98%, 100% { transform: rotate(-360deg); }
}

それぞれについて、 90deg (360deg/4ここで、 4 は画像の数です) 小さな一時停止を追加します。 各画像は、 5% 次のものにスライドする前の全体の期間の (27%-22%, 52%-47%など)。 を更新していきます animation-timing-function 使用して cubic-bezier() アニメーションを少し凝ったものにする関数:

これでスライダーは完璧です! 画像の周りを回転するカラフルな円形の境界線である最後の仕上げがまだ残っているため、ほぼ完璧です。 疑似要素を使用できます .gallery それを作るためのラッパー:

.gallery {
  padding: calc(var(--s) / 20); /* the padding is needed here */
  position: relative;
}
.gallery::after {
  content: "";
  position: absolute;
  inset: 0;
  padding: inherit; /* Inherits the same padding */
  border-radius: 50%;
  background: repeating-conic-gradient(#789048 0 30deg, #DFBA69 0 60deg);
  mask: 
    linear-gradient(#fff 0 0) content-box, 
    linear-gradient(#fff 0 0);
  mask-composite: exclude;
}
.gallery::after,
.gallery >img {
  animation: m 8s infinite cubic-bezier(.5, -0.2, .5, 1.2);
}

で円を作成しました 円錐勾配の繰り返し 使用中の背景用 マスキングトリック パディングされた領域のみを表示します。 次に、画像に定義したのと同じアニメーションを適用します。

完了です! クールな円形スライダーがあります。

もっと画像を追加しましょう

XNUMX つの画像で作業するのは良いことですが、任意の数の画像にスケーリングできればさらに良いでしょう。 結局のところ、これがイメージ スライダーの目的です。 検討できるはずです N 画像。

このために、Sass を導入してコードをより汎用的にします。 まず、画像数の変数を定義します ($n) 画像の数をハードコーディングしたすべての部分を更新します (4).

遅延から始めましょう:

.gallery > img:nth-child(2) { animation-delay: -2s; } /* -1 * 8s / 4 */
.gallery > img:nth-child(3) { animation-delay: -4s; } /* -2 * 8s / 4 */
.gallery > img:nth-child(4) { animation-delay: -6s; } /* -3 * 8s / 4 */

遅延の公式は (1 - $i)*duration/$nこれにより、次の Sass ループが得られます。

@for $i from 2 to ($n + 1) {
  .gallery > img:nth-child(#{$i}) {
    animation-delay: calc(#{(1 - $i) / $n} * 8s);
  }
}

本当に必要な場合は、期間を変数にすることもできます。 しかし、アニメーションに移りましょう:

@keyframes m {
  0%, 3% { transform: rotate(0); }
  22%, 27% { transform: rotate(-90deg); }
  47%, 52% { transform: rotate(-180deg); }
  72%, 77% { transform: rotate(-270deg); }
  98%, 100% {transform: rotate(-360deg); }
}

パターンをよりよく理解するために単純化してみましょう。

@keyframes m {
  0% { transform: rotate(0); }
  25% { transform: rotate(-90deg); }
  50% { transform: rotate(-180deg); }
  75% { transform: rotate(-270deg); }
  100% { transform: rotate(-360deg); }
}

各状態間のステップは次のようになります 25% —これは 100%/4 —そして、追加します -90deg 角度 - これは -360deg/4. つまり、代わりに次のようにループを記述できます。

@keyframes m {
  0% { transform: rotate(0); }
  @for $i from 1 to $n {
    #{($i / $n) * 100}% { transform: rotate(#{($i / $n) * -360}deg); }  
  }
  100% { transform: rotate(-360deg); }
}

それぞれの画像がかかるので 5% アニメーションの、これを変更します。

#{($i / $n) * 100}%

…これとともに:

#{($i / $n) * 100 - 2}%, #{($i / $n) * 100 + 3}%

それは、ことに留意すべきである 5% は、この例で選択した任意の値です。 各画像が表示されている時間を制御する変数にすることもできます。 簡単にするためにそれをスキップしますが、宿題として、それを試して、コメントで実装を共有することができます!

@keyframes m {
  0%,3% { transform: rotate(0); }
  @for $i from 1 to $n {
    #{($i / $n) * 100 - 2}%, #{($i / $n) * 100 + 3}% { transform: rotate(#{($i / $n) * -360}deg); }  
  }
  98%,100% { transform: rotate(-360deg); }
}

最後のビットは更新することです transform-origin. いくつかのジオメトリのトリックが必要になります。 イメージの数に関係なく、構成は常に同じです。 大きな円の中に画像 (小さな円) を配置し、半径の値を見つける必要があります。 R.

おそらく退屈な幾何学の説明は必要ないでしょう。 R:

R = S / (2 * sin(180deg / N))

これをパーセンテージで表すと、次のようになります。

R = 100% / (2 * sin(180deg / N)) = 50% / sin(180deg / N)

…つまり、 transform-origin 値は次のとおりです。

transform-origin: 50% (50% / math.sin(180deg / $n) + 50%);

終わったね! 任意の数の画像で動作するスライダーがあります!

そこに XNUMX つの画像を投げてみましょう。

必要な数の画像を追加して、 $n 画像の総数を持つ変数。

包み込む

CSS 変換と標準ジオメトリを使用したいくつかのトリックにより、多くのコードを必要としない、優れた円形スライダーを作成しました。 このスライダーの優れている点は、円があるため、無限のアニメーションを維持するためにわざわざ画像を複製する必要がないことです。 一回転したら最初の画像に戻ります!

タイムスタンプ:

より多くの CSSトリック