創造引人入勝的使用者介面通常需要在功能和視覺吸引力之間取得微妙的平衡。在本文中,我們將探索如何使用 Svelte 建立動態影像網格元件,該元件不僅可以有效管理狀態,而且可以在影像換入和換出時提供平滑、引人注目的過渡。
想像一個定期刷新自身的影像網格,各個卡片平滑地翻轉以顯示新影像。
這創建了一個引人入勝的顯示,非常適合展示團隊成員、產品目錄或任何大於一次顯示的圖像集合。
這就是我必須為顯示成員列表的圖像網格小部件構建的內容。會員圖像來自 API,並隨著時間的推移而增長。
我決定用 Svelte 建造這個,因為為什麼不呢? !
更認真地說,我想要的東西將被編譯為所需的必要程式碼量,並且在網站上佔用的空間非常小。
基於此,我有兩個選擇:
此外,我發現 svelte 模型更簡單、更直觀,因此如果有選擇,尤其是在像這樣的小項目上,我將預設使用它。
正如您進一步看到的那樣,與其他解決方案相比,svelte 使得處理許多小而複雜的狀態變化變得非常簡單(同樣,個人品味)。
通常,把事情搞砸的方法會更少。
我們的實作由兩個主要的 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
您可能想知道為什麼我們將 imagesInUse 與 imagesToUse 分開維護。這種分離有幾個重要目的:
影像交換過程是一個精心策劃的序列,可確保平滑過渡,同時保持網格完整性。讓我們一步步分解 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[]
此程式碼處理兩種情況:
接下來,我們在網格中隨機選擇要交換影像的位置:
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 } }
imagesSwapMap是觸發動畫的關鍵。當它更新時,相關的 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中文網其他相關文章!