vue3實現輪播渲染多張圖每張進行放大縮小拖拽功能互不影響

vue3實現輪播渲染多張圖每張進行放大縮小拖拽功能互不影響

1.以vue3中el-carousel輪播插件為例

 <div class="pic_view"><el-carousel height="100vh" :autoplay="false" ref="carouselRef" @change="handleCarouselChange"><el-carousel-item v-for="item in picLists" :key="item.id" :data-id="item.id"><div :style="{ backgroundColor: item.backgroundColor }" @wheel.prevent="rollImg" class="pic_set":data-id="item.id" ref="picSetRefs"><img :src="getUrl(`${item.url}`)" class="img" @mousedown="startMove($event, item.id)" :style="{left: imgStates[item.id]?.position.x || '25%',top: imgStates[item.id]?.position.y || '0',transform: `scale(${imgStates[item.id]?.zoom || 1})`}" /></div></el-carousel-item></el-carousel></div>

注意:getUrl方法是vite處理靜態資源圖片的,由于是本地為了測試,你們拿例子的時候注意點可以去掉這個方法放你們本地路徑渲染

2.事件

<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { getImageUrl } from '@/utils/pub-use'const getUrl = getImageUrlconst picLists = reactive([{ id: 1, url: 'yu1.webp', backgroundColor: '#6f6865' },{ id: 2, url: 'yu2.webp', backgroundColor: '#726A67' },{ id: 3, url: 'yu3.webp', backgroundColor: '#705947' },
])// 存儲每個圖片的狀態
const imgStates = reactive({})
const picSetRefs = ref([])
let currentImgId = ref(null)
let isDragging = false
let startX = 0
let startY = 0
let currentImgElement = null
let currentImgRect = null
let initialOffsetX = 0
let initialOffsetY = 0
// yzm提示:由于一般方法只適用單張,特此整合渲染多張圖操作
// 初始化圖片狀態
const initImgState = (id) => {if (!imgStates[id]) {imgStates[id] = {zoom: 0.8,position: { x: '25%', y: '0' },positionConverted: false}}
}// 將百分比位置轉換為像素值
const convertPositionToPixels = (id, element) => {const state = imgStates[id]if (!state || state.positionConverted) returnconst parent = element.parentElementif (!parent) return// 轉換水平位置if (typeof state.position.x === 'string' && state.position.x.includes('%')) {const percent = parseFloat(state.position.x)state.position.x = `${(percent / 100) * parent.clientWidth}px`}// 轉換垂直位置if (typeof state.position.y === 'string' && state.position.y.includes('%')) {const percent = parseFloat(state.position.y)state.position.y = `${(percent / 100) * parent.clientHeight}px`}// 更新元素樣式element.style.left = state.position.xelement.style.top = state.position.ystate.positionConverted = true
}// 輪播切換時更新當前圖片ID
const handleCarouselChange = (currentIndex) => {currentImgId.value = picLists[currentIndex].id// 確保新激活的圖片位置已轉換nextTick(() => {const activeIndex = currentIndexif (picSetRefs.value[activeIndex]) {const img = picSetRefs.value[activeIndex].querySelector('.img')if (img) {convertPositionToPixels(picLists[activeIndex].id, img)}}})
}// 拖動圖片相關函數
const startMove = (e, id) => {currentImgId.value = idinitImgState(id)currentImgElement = e.currentTarget// 確保位置已轉換為像素值if (!imgStates[id].positionConverted) {convertPositionToPixels(id, currentImgElement)}e.preventDefault()isDragging = true// 獲取當前圖片的位置和尺寸currentImgRect = currentImgElement.getBoundingClientRect()// 計算初始位置(直接使用狀態中的像素值)initialOffsetX = parseFloat(imgStates[id].position.x || '0')initialOffsetY = parseFloat(imgStates[id].position.y || '0')// 計算鼠標在圖片中的位置startX = e.clientX - currentImgRect.leftstartY = e.clientY - currentImgRect.topdocument.addEventListener('mousemove', move)document.addEventListener('mouseup', stopMove)
}const move = (e) => {if (!isDragging || !currentImgId.value || !currentImgElement) return// 計算新的位置(考慮縮放)const zoom = imgStates[currentImgId.value].zoom || 1const newX = initialOffsetX + (e.clientX - currentImgRect.left - startX) / zoomconst newY = initialOffsetY + (e.clientY - currentImgRect.top - startY) / zoom// 更新位置imgStates[currentImgId.value].position = {x: `${newX}px`,y: `${newY}px`}currentImgElement.style.left = `${newX}px`currentImgElement.style.top = `${newY}px`
}const stopMove = () => {isDragging = falsecurrentImgElement = nulldocument.removeEventListener('mousemove', move)document.removeEventListener('mouseup', stopMove)
}// 縮放圖片
const rollImg = (e) => {// 獲取事件發生的輪播項IDconst itemId = parseInt(e.currentTarget.getAttribute('data-id'))if (itemId !== currentImgId.value) returninitImgState(itemId)// 獲取當前操作的圖片元素const img = e.currentTarget.querySelector('.img')if (!img) return// 確保位置已轉換為像素值if (!imgStates[itemId].positionConverted) {convertPositionToPixels(itemId, img)}// 獲取當前縮放值const transform = img.style.transform || ''let zoom = imgStates[itemId].zoomif (transform.includes('scale')) {const match = transform.match(/scale\(([\d.]+)\)/)if (match && match[1]) {zoom = parseFloat(match[1])}}// 根據滾輪方向調整縮放const delta = e.deltaY || e.wheelDeltaconst direction = delta > 0 ? -1 : 1zoom += direction * 0.1// 限制縮放范圍zoom = Math.max(0.1, Math.min(zoom, 5))// 更新狀態和樣式imgStates[itemId].zoom = zoomimg.style.transform = `scale(${zoom})`e.preventDefault()
}// 組件卸載時清除事件
onBeforeUnmount(() => {stopMove()
})// 初始化所有圖片狀態
onMounted(() => {picLists.forEach(item => {initImgState(item.id)})// 設置初始當前圖片IDif (picLists.length > 0) {currentImgId.value = picLists[0].id}nextTick(() => {if (picSetRefs.value[0]) {const img = picSetRefs.value[0].querySelector('.img')if (img) {convertPositionToPixels(picLists[0].id, img)}}})
})
</script>

我給每張圖片設置不同背景,這個也要注意,不需要的話可以在HTML代碼塊里把背景操作去掉,geturl這個是我自己封裝的工具文件,你們用不到這個可以刪掉把圖片地址弄對就行

樣式

<style scoped lang="scss">
.pic_view {height: 100vh;overflow: hidden;:deep(.el-carousel) {height: 100%;.el-carousel__container {height: 100%;}.el-carousel__item {display: flex;justify-content: center;align-items: center;}}
}.pic_set {position: relative;width: 100%;height: 100%;overflow: hidden;display: flex;justify-content: center;align-items: center;touch-action: none;.img {position: absolute;height: 100%;max-width: 900px;min-height: 400px;margin-left: 2%;cursor: move;transform-origin: center center;transition: transform 0.1s ease;user-select: none;will-change: transform;}.imgLow {width: 100%;height: 80px;margin-top: 30vh;}
}
</style>

樣式加了過度以及中心放大縮小,看更加絲滑

以上就是三塊區域代碼

效果

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

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

相關文章

traceroute 使用說明

1、概述 Traceroute&#xff08;Windows 系統中為 tracert&#xff09;是一種網絡診斷工具&#xff0c;用于跟蹤數據包從本地設備到目標主機的傳輸路徑&#xff0c;并顯示沿途經過的每一跳&#xff08;路由器&#xff09;的延遲和 IP 地址。它通過發送不同 TTL&#xff08;生存…

用idea操作git緩存區回退、本地庫回退、遠程庫回退

前言 使用idea軟件操作git非常人性化和方便。 但是如果我的代碼使用git提交之后,我想回到以前的版本,此時需要進行git的版本回退。 提交代碼分為提交到緩存區、本地庫、遠程庫這3個過程。 下面我將介紹每個階段的提交對應的回退方法。 本篇文章是掌握git和使用idea操作git…

webpack+vite前端構建工具 - 3webpack處理js

3 webpack處理js webpack的核心——處理js文件&#xff0c;將模塊化的代碼打包。具體操作如下 es6轉化&#xff08;為兼容老瀏覽器&#xff0c;將es6轉化為es5&#xff09; babel-loader 代碼規范&#xff08;例如空格&#xff0c;縮進等代碼風格規范&#xff09; eslint 代碼…

Nginx轉發中相對路徑資源302問題的分析與解決

Nginx轉發中相對路徑資源302問題的分析與解決 典型案例&#xff1a;后端頁面引入./test.css的302問題 問題場景 假設我們有一個后端服務&#xff0c;其頁面中通過相對路徑引入了CSS文件&#xff1a; <!-- 后端頁面代碼 --> <link rel"stylesheet" href&…

Vue3 + TypeScript合并兩個列表到目標列表,并且進行排序,數組合并、集合合并、列表合并、list合并

在Vue 3 TypeScript中合并并排序兩個列表&#xff0c;可以通過以下步驟實現&#xff1a; 解決方案代碼 vue 復制 下載 <script setup lang"ts"> import { ref, computed } from vue;// 定義列表項類型 interface ListItem {id: number;name: string;valu…

Python-教程

1 需求 2 接口 3 示例 4 參考資料 Python 教程 — Python 3.13.5 文檔

Excel數據導出小記

文章目錄 前言一、DataTable >EXCEL二、DBReader >Excel &#xff08;NPOI&#xff09;三、分頁查詢 DbReader>Excel (MiniExcel)總結&#xff1a; 前言 最近經歷了一次數據量比較大的導出&#xff0c;也做了各種優化嘗試&#xff0c;這里稍記錄一下 一、DataTable …

深入理解鏈表數據結構:從Java LinkedList到自定義實現

引言 鏈表作為基礎數據結構之一&#xff0c;在Java集合框架中以LinkedList的形式提供。本文將深入分析Java原生LinkedList的實現機制&#xff0c;并介紹我自定義實現的MyLinkedList&#xff0c;最后對比兩者的設計差異與實現特點。 Java原生LinkedList解析 基本結構 Java的…

【深度學習】卷積神經網絡(CNN):計算機視覺的革命性引擎

卷積神經網絡&#xff08;CNN&#xff09;&#xff1a;計算機視覺的革命性引擎 一、算法背景&#xff1a;視覺智能的進化之路1.1 傳統視覺處理的困境1.2 神經科學的啟示 二、算法理論&#xff1a;CNN的核心架構2.1 基礎組成單元卷積層&#xff1a;特征提取引擎池化層&#xff1…

使用@SpringJUnitConfig注解開發遇到的空指針問題

Spring測試中的版本陷阱&#xff1a;SpringJUnitConfig與JUnit版本兼容性深度解析 一個看似簡單的空指針異常&#xff0c;背后可能隱藏著JUnit版本不匹配的“幽靈”。 一、SpringJUnitConfig&#xff1a;Spring與JUnit 5的橋梁 SpringJUnitConfig是Spring TestContext框架為**…

[2025CVPR]AdcSR:一種高效實世界圖像超分辨率的對抗擴散壓縮方法

目錄 1. 背景與挑戰 2. AdcSR模型概述 2.1 模型架構 2.2 訓練策略 3. 公式與原理 4. 創新點 5. 實驗與結果 5.1 實驗設置 5.2 結果對比 5.3 消融實驗 6. 結論 在計算機視覺領域&#xff0c;圖像超分辨率&#xff08;Image Super-Resolution, ISR&#xff09;一直是一…

Go 語言中的字符串基本操作

這篇文章已經放到騰訊智能工作臺的知識庫啦&#xff0c;鏈接在這里&#xff1a;ima.copilot-Go 入門到入土。要是你有啥不懂的地方&#xff0c;就去知識庫找 AI 聊一聊吧。 本篇將詳細講解 Go 語言中與字符串相關的操作。 1、rune 和 字符串長度 1、Go 函數語法約定 在開始…

數學建模會議筆記

看似優化模型 建立整數規劃模型 用優化軟件、啟發式方法、精確方法求解 建立圖論和組合優化模型用組合優化方法、啟發式方法求解 建立博弈論模型 數據統計分析與可視化- 數據擬合、參數估計、插值、數據的標準化、去偽補全相關度分析、分類、聚類等 最優化理論和方法 線性規劃…

學習昇騰開發的六天--ACL應用開發之運行第一個實例

1、下載一個實例&#xff0c;運行一個圖像分類實例&#xff08;環境&#xff1a;Ubuntu22.04&#xff0c;硬件&#xff1a;昇騰310B1&#xff0c;加速模塊&#xff1a;atlas 200i a2&#xff09; samples: CANN Samples - Gitee.com 目錄結構如下&#xff1a; ├── data │…

可靈AI-快手公司自主研發的一款AI視頻與圖像生成工具

可靈AI是由快手公司自主研發的一款AI視頻與圖像生成工具&#xff0c;于2024年6月正式推出。以下是對其的詳細介紹&#xff1a; 核心功能 AI視頻生成&#xff1a; 文生視頻&#xff1a;輸入文字描述&#xff0c;AI可自動生成匹配的視頻片段。圖生視頻&#xff1a;上傳圖片&…

創客匠人解析:存量時代創始人 IP 打造與免費流量池策略

在存量競爭的商業環境中&#xff0c;企業如何突破增長瓶頸&#xff1f;創客匠人結合新潮傳媒創始人張繼學的實戰洞察&#xff0c;揭示 “品牌 IP” 雙輪驅動下的免費流量池構建邏輯&#xff0c;為知識變現與創始人 IP 打造提供新思路。 一、存量時代的流量革命&#xff1a;從…

提升語義搜索效率:LangChain 與 Milvus 的混合搜索實戰

我從不幻想人生能夠毫無波折&#xff0c;但我期望遭遇困境之際&#xff0c;自身能夠成為它的克星。 概述 LangChain與Milvus的結合構建了一套高效的語義搜索系統。LangChain負責處理多模態數據&#xff08;如文本、PDF等&#xff09;的嵌入生成與任務編排&#xff0c;Milvus作…

MySQL配置簡單優化與讀寫測試

測試方法 先使用sysbench對默認配置的MySQL單節點進行壓測&#xff0c;單表數據量為100萬&#xff0c;數據庫總數據量為2000萬&#xff0c;每次壓測300秒。 sysbench --db-drivermysql --time300 --threads10 --report-interval1 \--mysql-host192.168.0.10 --mysql-port3306…

獵板深耕透明 PCB,解鎖電子設計新邊界

在電子技術快速迭代的當下&#xff0c;獵板始終關注行業前沿&#xff0c;透明 PCB 作為極具創新性的技術&#xff0c;正在改變電子設備的設計與應用格局。? 從傳統的綠色、棕色 PCB 到如今的透明 PCB&#xff0c;其突破在于特殊基材與導電材料的運用&#xff0c;實現 85%-92%…

FLAML:快速輕量級自動機器學習框架

概述 FLAML&#xff08;Fast and Lightweight AutoML&#xff09;是微軟開發的一個高效的自動機器學習&#xff08;AutoML&#xff09;框架。它專注于在有限的計算資源和時間約束下&#xff0c;自動化機器學習管道的構建過程&#xff0c;包括特征工程、模型選擇、超參數調優等…