Vue3輪播圖組件,當前輪播區域有當前圖和左右兩邊圖,兩邊圖各顯示一半,支持點擊跳轉和手動滑動切換

功能:

  • 自動循環播放(到達末尾后回到第一張)、可設置切換間隔時間(interval屬性)

  • 左右導航按鈕(可自定義顯示/隱藏)

  • 點擊底部指示器跳轉到指定幻燈片、且位置可調(輪播圖內部/外部)

  • 鼠標拖拽滑動(PC端)

  • 觸摸滑動(移動端適配)

  • 支持暫停/繼續自動播放(autoPlay控制)

  • 用戶交互(拖拽/點擊按鈕)時自動暫停輪播

  • 點擊幻燈片可跳轉頁面(這里是跳轉到詳情)

封裝好了,直接用就可以:components/Carousel.vue:

<template><div class="carousel-container"><!-- 左側導航按鈕 --><button class="nav-button prev" @click="prevSlide" v-if="showNavButtons">?</button><div class="carousel-viewport" ref="viewport"@mousedown="startDrag"@mousemove="handleDrag"@mouseup="endDrag"@mouseleave="endDrag"@touchstart="startDrag"@touchmove="handleDrag"@touchend="endDrag"><div class="carousel-track" :style="trackStyle"><div class="slide" v-for="(item, index) in items" :key="item.id"@click="handleSlideClick(index)"><img :src="item.cover" :alt="item.title"><div class="slide-title" :class="{ 'active': currentIndex === index }">{{ item.categoryTag }}</div></div></div></div><!-- 右側導航按鈕 --><button class="nav-button next" @click="nextSlide" v-if="showNavButtons">?</button><div class="indicators" :class="{ 'inside': indicatorsInside }"><span v-for="(item, index) in items" :key="item.id":class="{ 'active': currentIndex === index }"@click="goToSlide(index)"></span></div><!-- 標題和摘要顯示區域 --><div class="carousel-caption"><div class="carousel-title">{{ currentItem.title }}</div><div class="carousel-summary">{{ currentItem.summary }}</div></div></div>
</template><script setup>
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue';const props = defineProps({items: {  // 父組件傳過來的數據,下面會有模擬數據type: Array,required: true,default: () => []},interval: { // 控制自動輪播的切換時間間隔type: Number,default: 3000},autoPlay: { // 是否自動切換type: Boolean,default: true},initialIndex: { // 指定輪播圖初始顯示的第幾張幻燈片,默認顯示第 1 張type: Number,default: 0},indicatorsInside: { // 控制指示器輪播區域內部/外部顯示,true為在外部顯示,false為在內部顯示default: false},showNavButtons: {  // 控制左右按鈕顯示,這里默認隱藏type: Boolean,default: false}
});const currentIndex = ref(props.initialIndex);
const viewport = ref(null);
let autoPlayTimer = null;// 拖拽相關狀態
const isDragging = ref(false);
const startPos = ref(0);
const currentTranslate = ref(0);
const prevTranslate = ref(0);
const animationId = ref(null);
const dragDistance = ref(0);// 計算當前顯示的item
const currentItem = computed(() => {return props.items[currentIndex.value] || {};
});// 圖片寬度配置
const slideConfig = {fullWidth: 680,visiblePart: 320,gap: 20
};// 計算軌道偏移量
const trackStyle = computed(() => {if (isDragging.value) {return {transform: `translateX(${currentTranslate.value}px)`,transition: 'none'};}const offset = currentIndex.value * -(slideConfig.fullWidth + slideConfig.gap);return {transform: `translateX(${offset}px)`,transition: 'transform 0.5s ease'};
});// 開始拖拽
const startDrag = (e) => {stopAutoPlay();isDragging.value = true;startPos.value = getPositionX(e);prevTranslate.value = currentIndex.value * -(slideConfig.fullWidth + slideConfig.gap);currentTranslate.value = prevTranslate.value;dragDistance.value = 0;cancelAnimationFrame(animationId.value);
};// 處理拖拽
const handleDrag = (e) => {if (!isDragging.value) return;const currentPosition = getPositionX(e);const diff = currentPosition - startPos.value;currentTranslate.value = prevTranslate.value + diff;dragDistance.value = Math.abs(diff);
};// 結束拖拽
const endDrag = () => {if (!isDragging.value) return;const movedBy = currentTranslate.value - prevTranslate.value;// 如果拖動距離超過100px,則切換幻燈片if (movedBy < -100 && currentIndex.value < props.items.length - 1) {currentIndex.value += 1;} else if (movedBy > 100 && currentIndex.value > 0) {currentIndex.value -= 1;}isDragging.value = false;resetAutoPlay();
};// 獲取當前位置
const getPositionX = (e) => {return e.type.includes('mouse') ? e.pageX : e.touches[0].clientX;
};// 處理幻燈片點擊
const handleSlideClick = (index) => {// 如果拖動距離大于10px,則不觸發點擊事件if (dragDistance.value > 10) return;goToDetail(props.items[index].id);
};// 切換上一張
const prevSlide = () => {currentIndex.value = (currentIndex.value - 1 + props.items.length) % props.items.length;resetAutoPlay();
};// 切換下一張
const nextSlide = () => {currentIndex.value = (currentIndex.value + 1) % props.items.length;resetAutoPlay();
};// 跳轉到指定圖片
const goToSlide = (index) => {currentIndex.value = index;resetAutoPlay();
};// 自動播放控制
const startAutoPlay = () => {if (!props.autoPlay) return;stopAutoPlay();autoPlayTimer = setInterval(() => {nextSlide();}, props.interval);
};const stopAutoPlay = () => {if (autoPlayTimer) {clearInterval(autoPlayTimer);autoPlayTimer = null;}
};const resetAutoPlay = () => {if (props.autoPlay) {stopAutoPlay();startAutoPlay();}
};// 監聽autoPlay變化
watch(() => props.autoPlay, (newVal) => {if (newVal) {startAutoPlay();} else {stopAutoPlay();}
});// 監聽initialIndex變化
watch(() => props.initialIndex, (newVal) => {if (newVal >= 0 && newVal < props.items.length) {currentIndex.value = newVal;}
});const goToDetail = (id) => {navigateTo({ path: `/case/${id}.html` });
};onMounted(() => {startAutoPlay();
});onBeforeUnmount(() => {stopAutoPlay();cancelAnimationFrame(animationId.value);
});
</script><style scoped>
.carousel-container {position: relative;width: 100%;max-width: 1280px;margin: 0 auto;height: 400px;user-select: none;
}.carousel-viewport {position: relative;width: 100%;height: 100%;overflow: hidden;cursor: grab;
}.carousel-viewport:active {cursor: grabbing;
}.carousel-track {display: flex;height: 100%;padding: 0 calc(50% - 340px);will-change: transform;
}.slide {flex: 0 0 680px;height: 100%;margin-right: 20px;position: relative;cursor: pointer;touch-action: pan-y;
}.slide img {width: 100%;height: 100%;object-fit: cover;border-radius: 10px;pointer-events: none;
}.slide-title {position: absolute;bottom: 0;right: 0;background: rgba(0, 0, 0, 0.5);color: white;text-align: center;padding: 8px 17px;border-radius: 10px 0px 10px 0px;font-size: 14px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;transition: opacity 0.3s ease;
}/* 指示點樣式 - 默認在外部 */
.indicators {position: absolute;bottom: 20px;left: 0;right: 0;display: flex;justify-content: center;gap: 10px;z-index: 20;
}/* 指示點在內部的樣式 */
.indicators.inside {bottom: -30px;
}.indicators span {width: 10px;height: 10px;border-radius: 50%;background-color: #E0E0E0;cursor: pointer;transition: all 0.3s ease;
}.indicators span.active {background-color: #0A53B2;transform: scale(1.2);
}/* 標題和摘要樣式 */
.carousel-caption {margin-top: 70px;text-align: center;padding: 0 20px;text-align: center;
}.carousel-title {font-size: 26px;font-weight: bold;margin-bottom: 16px;color: #333;
}.carousel-summary {font-size: 16px;color: #808080;line-height: 1.5;
}/* 導航按鈕樣式 */
.nav-button {position: absolute;top: 50%;transform: translateY(-50%);background: rgba(0, 0, 0, 0.5);color: white;border: none;width: 40px;height: 40px;border-radius: 50%;font-size: 20px;cursor: pointer;z-index: 20;display: flex;align-items: center;justify-content: center;
}.nav-button:hover {background: rgba(0, 0, 0, 0.8);
}.prev {left: 20px;
}.next {right: 20px;
}/* 響應式調整 */
@media (max-width: 768px) {.nav-button {width: 30px;height: 30px;font-size: 16px;}.prev {left: 10px;}.next {right: 10px;}
}
</style>

父組件使用:

<Carousel :items="list" :interval="3000" :autoPlay="true" :initialIndex="1" :indicatorsInside="true"/>

list 模擬數據可以用這個:?

const list = ref([{"id": 303,"categoryTag": "政府辦公","title": "用智能化解決方案,助力政府完成辦公基礎設備搭建,系統管理全面升級","cover": "http://szdxyp.com/images/c02f612c-dd69-47ee-aafd-86aaa73df208.png","summary": "用智能化解決方案,簡介xxxxxxxxxxxxxxxxxxxx",},{"id": 304,"categoryTag": "金融風控","title": "財富基石:金融數據與資產積累","cover": "http://szdxyp.com/images/1d128ffa-f4f0-485e-878c-86a708769a19.png","summary": "用智能化金融方案,簡介xxxxxxxxxxxxxxxxxxxx硬幣象征財富,圖表代表金融數據,整體傳達了金融數據在財富積累中的關鍵作用。",},{"id": 305,"categoryTag": "政府辦公","title": "數字創想:代碼世界的團隊協作","cover": "http://szdxyp.com/images/080f8bdc-9133-4aaa-a34a-d9b965c23c24.png","summary": "用智能化金融方案,簡介xxxxxxxxxxxxxxxxxxxx突出了編程協作在構建數字未來中的基礎性作用,展示了團隊合作的重要性。",},{"id": 306,"categoryTag": "智慧教育","title": "《協同共生:城市脈動與綠色能源的雙向賦能》","cover": "http://szdxyp.com/images/3d670ed1-f68b-48d7-8bb6-d59d7d477846.png","summary": "展現出城市化進程與清潔能源發展的共生關系。左側圖片聚焦現代化城市的樓群林立與繁華交通,象征經濟與技術的高度聚合;右側呈現風力發電裝置與太陽能板的能量轉換場景,凸顯對可再生能源的實踐追求。兩者結合,揭示了在全球化與生態危機并存的當下,城市與自然的平衡共生成為可持續發展的核心命題",},{"id": 307,"categoryTag": "金融風控","title": "清潔能源:生態可持續的技術突圍","cover": "http://szdxyp.com/images/f4226060-347a-45d5-a379-3716189bc344.png","summary": "可再生能源實踐:\n右側風能、太陽能的規模化應用,體現了對化石能源的替代性突破,減少碳排放的同時,提高能源安全性與區域自主性。\n分布式能源趨勢:\n結合城市樓宇光伏、社區微電網等場景,清潔能源可深度融入城市基礎設施,形成“自給+共享”的能源網絡。",}
])

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87394.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87394.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87394.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

350+交付案例,高質量低成本構建智慧園區數字孿生交付新范式

在智慧園區建設領域&#xff0c;數字孿生技術正成為推動園區智能化轉型的核心引擎。山東融谷信息憑借其全要素、全周期、全方位的數字孿生交付能力&#xff0c;已成功交付350余個項目&#xff0c;覆蓋產業園區、智慧樓宇、智慧社區等多元場景&#xff0c;低成本高質量交付&…

OpenCV 圖像像素類型轉換與歸一化

一、知識點 1、OpenCV支持多種數據類型&#xff0c;每種類型都對應著不同的取值范圍。 (1)、CV_8U取值范圍[0, 255]。 (2)、CV_16U取值范圍[0, 65535]。 (3)、CV_32F取值范圍[0, 1]。 2、OpenCV提供convertTo()函數來轉換數據類型&#xff0c;提供normalize()函數來改…

機器學習算法_支持向量機

一、支持向量機 支持向量機只能做二分類任務 SVM全稱支持向量機&#xff0c;即尋找到一個超平面使樣本分成兩類&#xff0c;且間隔最大 硬間隔&#xff1a;如果樣本線性可分&#xff0c;在所有樣本分類都正確的情況下&#xff0c;尋找最大間隔&#xff1b;如果出現異常值或樣…

Linux : echo ~ tail 重定向符

&#x1f680; Linux 常用命令詳解&#xff1a;echo、tail 與重定向符號全解析&#xff08;含通俗案例&#xff09; &#x1f4c5; 更新時間&#xff1a;2025年6月17日 &#x1f3f7;? 標簽&#xff1a;Linux基礎 | Shell命令 | echo | tail | 輸出重定向 | Linux入門 文章目錄…

uniapp的更新流程【安卓、IOS、熱更新】

UniApp應用更新方案 兩種更新方式 APP全量升級&#xff1a;需要重新下載安裝包熱更新&#xff1a;通過下載wgt資源包實現&#xff0c;用戶只需重啟應用 Android更新實現 用戶需要授權安裝權限&#xff0c;流程為下載APK后自動彈出安裝界面 var dtask plus.downloader.cre…

火山引擎解碼生態型增長鐵律

“技術流量與力量的崛起&#xff0c;本質上是一場生態規模的競賽。每次浪潮的排頭兵&#xff0c;都是指尖沾著代碼的開發者——互聯網時代的Linux社區讓開源席卷全球&#xff0c;移動互聯網的App Store催生百萬開發者&#xff0c;而今天&#xff0c;大模型正在用API重構產業。”…

警惕GO的重復初始化

go的初始化方式有很多種&#xff0c;在某些情況下容易引起重復初始化導致錯誤。 事例如下&#xff1a; 當使用gorm連接數據庫時定義了全局DB var DB *gorm.DB 但是在后面某個函數內部初始化時導致DB重新初始化變成了局部變量&#xff0c;導致原來的全局變量DB還是nil func I…

python校園服務交流系統

目錄 技術棧介紹具體實現截圖系統設計研究方法&#xff1a;設計步驟設計流程核心代碼部分展示研究方法詳細視頻演示試驗方案論文大綱源碼獲取/詳細視頻演示 技術棧介紹 Django-SpringBoot-php-Node.js-flask 本課題的研究方法和研究步驟基本合理&#xff0c;難度適中&#xf…

AlexNet:圖像分類領域的里程碑網絡及其創新剖析

文章目錄 前言AlexNet一、網絡的背景二、網絡結構三、網絡的創新3.1 首次使用GPU訓練網絡3.2 使用Relu激活函數3.2.1 sigmoid激活函數和tanh激活函數3.2.1.1 sigmoid激活函數3.2.1.2 tanh激活函數 3.3 Relu激活函數3.4 使用LRN局部響應歸一化(已棄用)3.4.1 LRN的定義與起源3.4.…

iOS性能調優實踐:結合KeyMob等多個工具提升應用穩定性與流暢度

在iOS應用開發中&#xff0c;性能問題往往難以通過單一工具輕松解決。尤其是當App面臨用戶反饋的流暢度差、卡頓嚴重、內存泄漏等問題時&#xff0c;開發者需要依靠多種工具的組合&#xff0c;才能有效地排查和優化性能瓶頸。 在我們最近的一個項目中&#xff0c;開發團隊在處…

球形波方程的推導與解法

題目 問題 6. 一個球形波是三維波動方程的解,形式為 u ( r , t ) u(r,t) u(r,t),其中 r r r 是到原點的距離(球坐標)。波動方程的形式為: u t t = c 2 ( u r r + 2 r u r ) (球形波方程) . u_{tt} = c^{2} \left( u_{rr} + \frac{2}{r} u_{r} \right) \quad \text{(球形…

自動打電話軟件設計與實現

文章目錄 方案概述實現代碼1. 安裝必要的庫2. 主程序代碼3. HTML模板 (templates/index.html) 功能說明部署說明擴展功能建議注意事項 方案概述 使用Twilio的API進行電話呼叫實現基本的呼叫邏輯添加簡單的用戶界面 實現代碼 1. 安裝必要的庫 pip install twilio flask2. 主…

RedissonLock源代碼分析與鎖應用

文章目錄 前言一、RedissonLock源代碼分析1.1 嘗試加鎖2.2 解鎖 二、鎖業務應用1.服務層方法注解方式 注入鎖1.1 定義DistributedLock 注解類1.2 定義DistributedLockAspect 切片類1.3 嘗試獲取鎖代碼片斷1.4 釋放鎖代碼片斷1.5 服務層注入鎖注解 2.代碼行加鎖2.1 pom.xml文件引…

深入理解mysql索引

一、什么是索引&#xff1f; 索引&#xff08;Index&#xff09; 是數據庫管理系統中一種特殊的數據結構&#xff0c;存儲在磁盤上。它包含對數據表中一列或多列的值進行排序&#xff0c;并存儲了指向表中實際數據行物理位置或主鍵值的引用指針。可以把它類比為書籍的目錄&…

VMware vSphere Foundation 9.0 技術手冊 —— Ⅰ 安裝 ESXi 9.0 (虛擬機)

目錄 1. 安裝 ESXi 9.0 (虛擬機)&#xff08;1&#xff09;ESXi Standard Boot Menu&#xff08;2&#xff09;ESXi 安裝導向&#xff08;3&#xff09;最終用戶許可協議&#xff08;4&#xff09;選擇系統盤&#xff08;5&#xff09;選擇鍵盤類型&#xff08;6&#xff09;設…

UE5 游戲模板 —— TopDownGame 俯視角游戲

UE5 游戲模板 —— TopDownGame 俯視角游戲 前言一、模塊導入二、TopDownGameMode三、TopDownPlayerController1、構造函數2、SetupInputComponent初始化新輸入系統處理輸入邏輯 四、TopDownCharacter五、射線檢測總結 前言 上一篇文章介紹了一下PuzzleGame模板的流程&#xf…

基于深度學習的智能圖像分割系統:技術與實踐

前言 圖像分割是計算機視覺領域中的一個核心任務&#xff0c;其目標是將圖像劃分為多個有意義的區域或對象。圖像分割在醫學影像分析、自動駕駛、安防監控等多個領域有著廣泛的應用。近年來&#xff0c;深度學習技術&#xff0c;尤其是卷積神經網絡&#xff08;CNN&#xff09;…

【學習筆記】2.2 Encoder-Decoder

參考資料&#xff1a;https://github.com/datawhalechina/happy-llm 在 Transformer 中&#xff0c;使用注意力機制的是其兩個核心組件——Encoder&#xff08;編碼器&#xff09;和 Decoder&#xff08;解碼器&#xff09;。 2.2.1 Seq2Seq 模型 Seq2Seq&#xff08;序列到…

# 材料力學押題

材料力學押題 文章目錄 材料力學押題第一題第二題組合變形彎曲變形 第一題 Q 求力作用的銷釘位置的豎直偏移距離。 S 方法一:能量方法 材料應變能計算為: U ∫ 內力 2 2 剛度 d A U\int \frac{\text{內力}^2}{2\times 剛度}\text{d}A U∫2剛度內力2?dA 克拉珀龍原理&…

uniapp項目之小兔鮮兒小程序商城(一) 項目介紹,技術棧,小程序的基礎架構,封裝攔截器和請求函數

文章目錄 一.項目介紹和前置內容1.重要鏈接2.技術棧 二.創建uniapp項目1.使用HBuilderX創建2.使用命令行創建3.如何使用vscode開發uniapp項目?step1:把項目拉入vscode,開始下相關插件step2:ts類型校驗step3:設置json文件可以允許注釋 4.pages.json文件的作用是什么?5.示例:在…