# Nuxt3 Swiper 運用 ## 套件安裝 ``` npm i swiper ``` ## [Swiper 縮圖圖庫(Thumbs gallery)](https://swiperjs.com/) 版本:swiper 11.2.6 本案例擁有展示圖及所有圖片縮圖,並另外設置上下張圖片切換鈕可自行擺放按鈕位置 :::spoiler 結果示意圖 ![swiper_Thumbs_gallery](https://hackmd.io/_uploads/BJhOxlzCyx.svg) ::: ### 程式碼 ```htmlembedded= <template> <template v-if="data"> <div class="showBox"> <swiper :style="{ '--swiper-navigation-color': '#fff', '--swiper-pagination-color': '#fff', }" :spaceBetween="10" :navigation="{ nextEl: '.nextBtn', prevEl: '.prevBtn', }" :thumbs="{ swiper: thumbsSwiper }" :modules="modules" class="mySwiper2" @swiper="onSwiper" @slideChange="onSlideChange" > <template v-for="(item, index) in data"> <swiper-slide class="imgBlack"> <div class="imgBox"> <img width="1290.59" height="667.109" :src="item" :alt="'展示圖檔_' + (index + 1)" loading="lazy"/> </div> </swiper-slide> </template> </swiper> </div> <div class="switchBtnBox"> <div class="prevBtn" :class="{'noPrev' : currentSlideIndex == 0}">上一張</div> <div class="nextBtn" :class="{'noNext' : currentSlideIndex == (data.images?.length - 1)}">下一張</div> </div> <div class="thumbnailBox"> <swiper @swiper="setThumbsSwiper" :spaceBetween="10" :slidesPerView="setSlidesPerView" :freeMode="true" :watchSlidesProgress="true" :modules="modules" class="mySwiper" > <template v-for="(item, index) in data"> <swiper-slide class="imgBlack"> <img width="114.594" height="185.594" :src="item" :alt="'燈箱選擇圖檔_' + (index + 1)" loading="lazy" /> </swiper-slide> </template> </swiper> </div> </template> </template> <script setup> import { Swiper, SwiperSlide } from 'swiper/vue'; import { FreeMode, Navigation, Thumbs } from 'swiper/modules'; import 'swiper/css'; import 'swiper/css/free-mode'; import 'swiper/css/navigation'; import 'swiper/css/thumbs'; import { onMounted } from 'vue'; const modules= [FreeMode, Navigation, Thumbs] // swiper套件連動 縮圖及顯示圖片 const thumbsSwiper = ref(null) const setThumbsSwiper = (swiper) =>{ thumbsSwiper.value = swiper } const currentSlideIndex = ref(1); const swiperInstance = ref(null); // 當 Swiper 初始化時,儲存 Swiper 實例 const onSwiper = (swiper) => { swiperInstance.value = swiper; currentSlideIndex.value = swiper.activeIndex; // 設置初始索引 }; // 當輪播切換時,更新當前索引 const onSlideChange = (swiper) => { currentSlideIndex.value = swiper.activeIndex; }; // 設置縮圖顯示幾張 const setSlidesPerView = ref(6) if(data.value?.length){ if(data.value?.length >= 6){ setSlidesPerView.value = 6 } else { setSlidesPerView.value = data.value?.length || 6 } } // 測試檔案 const data = ref([ "https://picsum.photos/id/222/1200/600", "https://picsum.photos/id/223/1200/600", "https://picsum.photos/id/214/1200/600", "https://picsum.photos/id/225/1200/600", "https://picsum.photos/id/216/1200/600", "https://picsum.photos/id/227/1200/600", "https://picsum.photos/id/228/1200/600", "https://picsum.photos/id/229/1200/600" ]) const switchImg = (index) =>{ if(!index) retrun; if (swiperInstance.value) { swiperInstance.value.slideTo(imgIndex, 300); // 切換主輪播到該索引,300ms 動畫 } if (thumbsSwiper.value) { thumbsSwiper.value.slideTo(imgIndex, 300); // 同步縮圖輪播 } } </script> <style lang="scss"> // 文字設置 @mixin fontStyle($font_fontWeight, $font_fontSize, $lineHeight: 1.5) { font-weight: $font_fontWeight; font-size: $font_fontSize; line-height: $lineHeight; } @mixin Body_R_16() { @include fontStyle(400, 1.6rem); } // 色彩設置 $switchBtnTextColor:rgba(59, 54, 53, 1); $switchBtnDisabledTextColor:rgba(119, 119, 119, 1); // 主要樣式設置 .showBox{ width: 100%; aspect-ratio: 990/580; display: flex; justify-content: center; align-items: center; @media screen and (max-width: 960px){ aspect-ratio: 375/220; } .mySwiper2{ width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; .imgBlack{ display: flex; justify-content: center; align-items: center; .imgBox{ width: 100%; height: 100%; user-select: none; -moz-user-select: none; -webkit-user-select: none; img{ display: block; width: 100%; height: 100%; // object-fit: contain; object-fit: cover; } } } } } .switchBtnBox{ width: 100%; position: relative; display: flex; justify-content: flex-end; column-gap: 2rem; margin-top: 2.1rem; margin-bottom: .7rem; @media screen and (max-width: 960px){ display: none; } .nextBtn, .prevBtn{ cursor: pointer; width: max-content; color: $switchBtnTextColor; user-select: none; -moz-user-select: none; -webkit-user-select: none; @include Body_R_16(); &.noPrev, &.noNext{ color: $switchBtnDisabledTextColor; cursor: not-allowed; } } } .thumbnailBox{ width: 100%; @media screen and (max-width: 960px){ padding-left: 2rem; } .mySwiper{ width: 100%; height: 100%; .imgBlack{ img{ display: block; width: 100%; height: 100%; object-fit: contain; cursor: pointer; } } } } </style> ``` ##### 參考資料 [參考網址:swiper官網 範例](https://swiperjs.com/demos)