使用 Svelte 構(gòu)建動(dòng)態(tài)圖像網(wǎng)格:實(shí)現(xiàn)翻轉(zhuǎn)卡過(guò)渡
Nov 25, 2024 am 05:20 AM創(chuàng)建引人入勝的用戶(hù)界面通常需要在功能和視覺(jué)吸引力之間取得微妙的平衡。在本文中,我們將探索如何使用 Svelte 構(gòu)建動(dòng)態(tài)圖像網(wǎng)格組件,該組件不僅可以有效管理狀態(tài),而且可以在圖像換入和換出時(shí)提供平滑、引人注目的過(guò)渡。
愿景
想象一個(gè)定期刷新自身的圖像網(wǎng)格,各個(gè)卡片平滑地翻轉(zhuǎn)以顯示新圖像。
這創(chuàng)建了一個(gè)引人入勝的顯示,非常適合展示團(tuán)隊(duì)成員、產(chǎn)品目錄或任何大于一次顯示的圖像集合。
這就是我必須為顯示成員列表的圖像網(wǎng)格小部件構(gòu)建的內(nèi)容。會(huì)員圖像來(lái)自 API,并隨著時(shí)間的推移而增長(zhǎng)。
我決定用 Svelte 構(gòu)建這個(gè),因?yàn)闉槭裁床荒???/p>
更認(rèn)真地說(shuō),我想要的東西將被編譯為所需的必要代碼量,并且在網(wǎng)站上占用的空間非常小。
基于此,我有兩個(gè)選擇:
- 使用 vanilla javascript 構(gòu)建它
- 使用一個(gè) javascript 庫(kù),它將生成一個(gè)非常小的包,特別是考慮到該項(xiàng)目也非常小。
此外,我發(fā)現(xiàn) svelte 模型更簡(jiǎn)單、更直觀,因此如果有選擇,尤其是在像這樣的小項(xiàng)目上,我將默認(rèn)使用它。
正如您進(jìn)一步看到的那樣,與其他解決方案相比,svelte 使得處理許多小而復(fù)雜的狀態(tài)變化變得非常簡(jiǎn)單(同樣,個(gè)人品味)。
通常,把事情搞砸的方法會(huì)更少。
核心組件
我們的實(shí)現(xiàn)由兩個(gè)主要的 Svelte 組件組成:
- App.svelte - 管理網(wǎng)格和協(xié)調(diào)圖像交換的主要組件
- MemberImageCard.svelte - 處理翻轉(zhuǎn)動(dòng)畫(huà)和圖像顯示的單獨(dú)卡片
狀態(tài)管理:網(wǎng)格背后的大腦
我們小部件的核心在于它的狀態(tài)管理。我們需要追蹤幾條信息:
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
為什么要單獨(dú)跟蹤當(dāng)前狀態(tài)?
您可能想知道為什么我們將 imagesInUse 與 imagesToUse 分開(kāi)維護(hù)。這種分離有幾個(gè)重要目的:
- 它為當(dāng)前網(wǎng)格狀態(tài)提供單一事實(shí)來(lái)源
- 它有助于防止重復(fù)的圖像出現(xiàn)在網(wǎng)格中
- 它可以實(shí)現(xiàn)高效更新,無(wú)需完全網(wǎng)格重新渲染
- 它在交換操作期間保持網(wǎng)格完整性
交換編排:詳細(xì)觀察
圖像交換過(guò)程是一個(gè)精心策劃的序列,可確保平滑過(guò)渡,同時(shí)保持網(wǎng)格完整性。讓我們一步步分解 switchImages 函數(shù):
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
1. 從池中選擇圖像
首先,我們需要確定剩余池中的哪些圖像將用于交換:
const switchImages = () => { let newImagesSwapMap = new Map<number, Image>() let remainingImagesToUse let newRemainingImages: Image[]
此代碼處理兩種情況:
- 如果剩余圖像不足,我們會(huì)使用所有圖像
- 否則,我們從池中獲取最后 N 張圖像,其中 N 是 NUMBER_OF_IMAGES_TO_SWITCH
2. 選擇網(wǎng)格位置
接下來(lái),我們?cè)诰W(wǎng)格中隨機(jī)選擇要交換圖像的位置:
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); }
這會(huì)在我們的網(wǎng)格大小內(nèi)創(chuàng)建一個(gè)隨機(jī)索引數(shù)組。例如,如果 NUMBER_OF_IMAGES_TO_SWITCH 為 1 并且 NUMBER_OF_IMAGES_TO_USE 為 16,我們可能會(huì)得到 [7],表示我們將交換網(wǎng)格中位置 7 的圖像。
3. 防止重復(fù)
在執(zhí)行任何交換之前,我們檢查新圖像是否已顯示:
indexesToSwap = Array(NUMBER_OF_IMAGES_TO_SWITCH) .fill(null) .map(() => Math.floor(Math.random() * NUMBER_OF_IMAGES_TO_USE));
此功能可防止同一圖像在我們的網(wǎng)格中多次出現(xiàn)。
4. 互換操作
現(xiàn)在是核心交換邏輯:
const imageIsInUse = (image: Image) => { const inUse = imagesInUse.find((img: Image) => image.picture_url === img.picture_url); return inUse; };
讓我們分解一下每次交換中會(huì)發(fā)生什么:
- 我們得到隨機(jī)選擇的位置(索引)
- 我們識(shí)別該位置的當(dāng)前圖像(imageToSwap)
- 我們從池中獲取新圖像 (imageToSwapWith)
- 如果新圖像有效且尚未顯示:
- 我們將交換記錄在imagesSwapMap中
- 我們更新imagesInUse中的網(wǎng)格狀態(tài)
- 我們?cè)陂_(kāi)始時(shí)將舊圖像添加回池中
5. 確定狀態(tài)
執(zhí)行所有交換后,我們更新?tīng)顟B(tài):
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 } }
6. 觸發(fā)動(dòng)畫(huà)
imagesSwapMap是觸發(fā)動(dòng)畫(huà)的關(guān)鍵。當(dāng)它更新時(shí),相關(guān)的 MemberImageCard 組件會(huì)做出反應(yīng):
remainingImages = newRemainingImages; imagesInUse = imagesInUse;
MemberImageCard 中的此反應(yīng)語(yǔ)句:
- 檢測(cè)其位置何時(shí)涉及交換
- 在卡片的反面加載新圖像
- 通過(guò)改變faceOnDisplay觸發(fā)翻轉(zhuǎn)動(dòng)畫(huà)
- 重置圖像加載狀態(tài)以實(shí)現(xiàn)平滑過(guò)渡
這個(gè)系統(tǒng)的美妙之處在于它保持流暢的用戶(hù)體驗(yàn),同時(shí)確保:
- 網(wǎng)格中沒(méi)有出現(xiàn)重復(fù)的圖像
- 圖像高效循環(huán)
- 網(wǎng)格始終保持其結(jié)構(gòu)
- 動(dòng)畫(huà)順利且可預(yù)測(cè)地發(fā)生
- 失敗的交換(由于重復(fù))會(huì)得到妥善處理
翻轉(zhuǎn)動(dòng)畫(huà):使其平滑
每個(gè) MemberImageCard 組件使用 CSS 變換和過(guò)渡來(lái)管理自己的翻轉(zhuǎn)動(dòng)畫(huà)。神奇的事情是通過(guò)狀態(tài)跟蹤和 CSS 的結(jié)合來(lái)實(shí)現(xiàn)的:
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[]
當(dāng)圖像需要交換時(shí),我們:
- 在反面加載新圖像
- 觸發(fā)翻轉(zhuǎn)動(dòng)畫(huà)
- 翻轉(zhuǎn)完成后清理舊圖像
漸進(jìn)式加載以獲得更好的用戶(hù)體驗(yàn)
為了增強(qiáng)用戶(hù)體驗(yàn),我們實(shí)現(xiàn)了漸進(jìn)式加載效果:
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); }
加載后圖像開(kāi)始模糊并平滑淡入,提供精美的外觀和感覺(jué)。
安排舞蹈
定期圖像交換是使用 Svelte 的 onMount 生命周期函數(shù)安排的:
indexesToSwap = Array(NUMBER_OF_IMAGES_TO_SWITCH) .fill(null) .map(() => Math.floor(Math.random() * NUMBER_OF_IMAGES_TO_USE));
結(jié)論
此實(shí)現(xiàn)展示了 Svelte 反應(yīng)功能與現(xiàn)代 CSS 轉(zhuǎn)換相結(jié)合的強(qiáng)大功能,可創(chuàng)建動(dòng)態(tài)、引人入勝的 UI 組件。
以上是使用 Svelte 構(gòu)建動(dòng)態(tài)圖像網(wǎng)格:實(shí)現(xiàn)翻轉(zhuǎn)卡過(guò)渡的詳細(xì)內(nèi)容。更多信息請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線(xiàn)人工智能工具。

Clothoff.io
AI脫衣機(jī)

Video Face Swap
使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱門(mén)文章

熱工具

記事本++7.3.1
好用且免費(fèi)的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強(qiáng)大的PHP集成開(kāi)發(fā)環(huán)境

Dreamweaver CS6
視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版
神級(jí)代碼編輯軟件(SublimeText3)

熱門(mén)話(huà)題

javascriptisidealforwebdevelogment,whilejavasuitslarge-scaleapplicationsandandandroiddevelopment.1)javascriptexceleatingingingingingingingbeatingwebexperienceswebexperienceswebexperiencesandfull-stackdeevermentwithnode.js.2)

在JavaScript中,選擇單行注釋?zhuān)?/)還是多行注釋?zhuān)?/)取決于注釋的目的和項(xiàng)目需求:1.使用單行注釋進(jìn)行快速、內(nèi)聯(lián)的解釋?zhuān)?.使用多行注釋進(jìn)行詳細(xì)的文檔說(shuō)明;3.保持注釋風(fēng)格的一致性;4.避免過(guò)度注釋?zhuān)?.確保注釋與代碼同步更新。選擇合適的注釋風(fēng)格有助于提高代碼的可讀性和可維護(hù)性。

是的,javascriptcommentsarenectary和shouldshouldshouldseffectional.1)他們通過(guò)codeLogicAndIntentsgudedepleders,2)asevitalincomplexprojects,和3)handhanceClaritywithOutClutteringClutteringThecode。

Java和JavaScript是不同的編程語(yǔ)言,各自適用于不同的應(yīng)用場(chǎng)景。Java用于大型企業(yè)和移動(dòng)應(yīng)用開(kāi)發(fā),而JavaScript主要用于網(wǎng)頁(yè)開(kāi)發(fā)。

JavascriptconcommentsenceenceEncorenceEnterential gransimenting,reading and guidingCodeeXecution.1)單inecommentsareusedforquickexplanations.2)多l(xiāng)inecommentsexplaincomplexlogicorprovideDocumentation.3)

評(píng)論arecrucialinjavascriptformaintainingclarityclarityandfosteringCollaboration.1)heelpindebugging,登機(jī),andOnderStandingCodeeVolution.2)使用林格forquickexexplanations andmentmentsmmentsmmentsmments andmmentsfordeffordEffordEffordEffordEffordEffordEffordEffordEddeScriptions.3)bestcractices.3)bestcracticesincracticesinclud

JavaScripthasseveralprimitivedatatypes:Number,String,Boolean,Undefined,Null,Symbol,andBigInt,andnon-primitivetypeslikeObjectandArray.Understandingtheseiscrucialforwritingefficient,bug-freecode:1)Numberusesa64-bitformat,leadingtofloating-pointissuesli

JavaScriptIspreferredforredforwebdevelverment,而Javaisbetterforlarge-ScalebackendsystystemsandSandAndRoidApps.1)JavascriptexcelcelsincreatingInteractiveWebexperienceswebexperienceswithitswithitsdynamicnnamicnnamicnnamicnnamicnemicnemicnemicnemicnemicnemicnemicnemicnddommanipulation.2)
