魅力的なユーザー インターフェイスを作成するには、多くの場合、機能と視覚的な魅力の間の微妙なバランスが必要です。この記事では、Svelte を使用して、状態を効率的に管理するだけでなく、画像の入れ替え時にスムーズで目を引く遷移を提供する動的画像グリッド コンポーネントを構築する方法を検討します。
画像のグリッドが定期的に更新され、個々のカードが滑らかにめくられて新しい画像が表示されることを想像してください。
これにより、チーム メンバー、製品カタログ、または一度に表示できるサイズより大きい画像のコレクションを紹介するのに最適な魅力的なディスプレイが作成されます。
これは、メンバー リストを表示する画像グリッド ウィジェット用に構築する必要があったものです。メンバーの画像は API から取得され、時間の経過とともに増加します。
これを Svelte で構築することにしたのは、なぜそうしないのですか?!
もっと真剣に考えれば、必要な量のコードにコンパイルされ、Web サイト上の占有面積が非常に小さいものが欲しかったのです。
それに基づいて、私には 2 つの選択肢がありました:
さらに、洗練されたモデルのほうがシンプルで直感的だと思うので、特に今回のような小規模なプロジェクトでは、選択肢があればそれをデフォルトにします。
もう少し詳しく見ると、svelte を使用すると、他のソリューションと比較して、多くの小さくて複雑な状態変更の処理が非常に簡単になります (これも個人的な好みです)。
通常、物事を台無しにする方法は少なくなります。
私たちの実装は 2 つの主要な Svelte コンポーネントで構成されています:
ウィジェットの中心はその状態管理にあります。いくつかの情報を追跡する必要があります:
let allImages: Image[]; // All available images let imagesToUse: Image[] = []; // Initial grid images let imagesInUse: Image[] = []; // Current grid state let remainingImages: Image[] = []; // Pool of unused images let imagesSwapMap = new Map<number, Image>(); // Tracks pending swaps
なぜimagesToUseとは別にimagesInUseを維持するのか疑問に思われるかもしれません。この分離には、いくつかの重要な目的があります:
画像の交換プロセスは、グリッドの整合性を維持しながらスムーズな移行を保証する慎重に調整されたシーケンスです。 switchImages 関数を段階的に見てみましょう:
let allImages: Image[]; // All available images let imagesToUse: Image[] = []; // Initial grid images let imagesInUse: Image[] = []; // Current grid state let remainingImages: Image[] = []; // Pool of unused images let imagesSwapMap = new Map<number, Image>(); // Tracks pending swaps
まず、残りのプールからどの画像を交換に使用するかを決定する必要があります。
const switchImages = () => { let newImagesSwapMap = new Map<number, Image>() let remainingImagesToUse let newRemainingImages: Image[]
このコードは 2 つのシナリオを処理します:
次に、画像を交換するグリッド内の位置をランダムに選択します。
if (remainingImages.length <= NUMBER_OF_IMAGES_TO_SWITCH) { // If we have fewer remaining images than needed, use all of them remainingImagesToUse = remainingImages.slice(0); newRemainingImages = []; } else { // Take the last N images from the remaining pool remainingImagesToUse = remainingImages.slice(-NUMBER_OF_IMAGES_TO_SWITCH); // Keep the rest for future swaps newRemainingImages = remainingImages.slice(0, -NUMBER_OF_IMAGES_TO_SWITCH); }
これにより、グリッド サイズ内でランダムなインデックスの配列が作成されます。たとえば、NUMBER_OF_IMAGES_TO_SWITCH が 1、NUMBER_OF_IMAGES_TO_USE が 16 の場合、[7] が得られ、グリッドの 7 番目の位置で画像を交換することを示します。
交換を実行する前に、新しい画像がすでに表示されているかどうかを確認します。
indexesToSwap = Array(NUMBER_OF_IMAGES_TO_SWITCH) .fill(null) .map(() => Math.floor(Math.random() * NUMBER_OF_IMAGES_TO_USE));
この機能は、グリッド内に同じ画像が複数回表示されるのを防ぎます。
ここでコア交換ロジックを説明します:
const imageIsInUse = (image: Image) => { const inUse = imagesInUse.find((img: Image) => image.picture_url === img.picture_url); return inUse; };
各スワップで何が起こるかを詳しく見てみましょう:
すべてのスワップを実行した後、状態を更新します。
for (let i = 0; i < indexesToSwap.length; i++) { let index = indexesToSwap[i]; let imageToSwap = imagesInUse[index]; // Current image in the grid let imageToSwapWith = remainingImagesToUse.pop(); // New image to display if (imageToSwapWith && !imageIsInUse(imageToSwapWith)) { // Record the swap in our map newImagesSwapMap.set(index, imageToSwapWith); // Update the swap map to trigger component updates imagesSwapMap = newImagesSwapMap; // Update the grid state imagesInUse[index] = imageToSwapWith; // Add the old image back to the pool newRemainingImages.unshift(imageToSwap); } else { return; // Skip if the image is already in use } }
imageSwapMap はアニメーションをトリガーするための鍵です。更新すると、関連する MemberImageCard コンポーネントが反応します:
remainingImages = newRemainingImages; imagesInUse = imagesInUse;
MemberImageCard のこのリアクティブ ステートメント:
このシステムの利点は、次のことを保証しながらスムーズなユーザー エクスペリエンスを維持できることです。
各 MemberImageCard コンポーネントは、CSS 変換とトランジションを使用して独自の反転アニメーションを管理します。この魔法は、状態追跡と CSS の組み合わせによって起こります。
let allImages: Image[]; // All available images let imagesToUse: Image[] = []; // Initial grid images let imagesInUse: Image[] = []; // Current grid state let remainingImages: Image[] = []; // Pool of unused images let imagesSwapMap = new Map<number, Image>(); // Tracks pending swaps
const switchImages = () => { let newImagesSwapMap = new Map<number, Image>() let remainingImagesToUse let newRemainingImages: Image[]
画像を交換する必要がある場合、次のことを行います:
ユーザー エクスペリエンスを向上させるために、プログレッシブ ローディング効果を実装しました。
if (remainingImages.length <= NUMBER_OF_IMAGES_TO_SWITCH) { // If we have fewer remaining images than needed, use all of them remainingImagesToUse = remainingImages.slice(0); newRemainingImages = []; } else { // Take the last N images from the remaining pool remainingImagesToUse = remainingImages.slice(-NUMBER_OF_IMAGES_TO_SWITCH); // Keep the rest for future swaps newRemainingImages = remainingImages.slice(0, -NUMBER_OF_IMAGES_TO_SWITCH); }
画像は読み込まれるとぼやけ始め、スムーズにフェードインし、洗練された外観と感触を提供します。
定期的なイメージのスワップは、Svelte の onMount ライフサイクル関数を使用してスケジュールされます。
indexesToSwap = Array(NUMBER_OF_IMAGES_TO_SWITCH) .fill(null) .map(() => Math.floor(Math.random() * NUMBER_OF_IMAGES_TO_USE));
この実装は、Svelte のリアクティブ機能と最新の CSS 変換を組み合わせて、動的で魅力的な UI コンポーネントを作成する能力を示しています。
以上がSvelte を使用した動的な画像グリッドの構築: フリップ カード トランジションの実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。