最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3中使用medium-zoom方法實例代碼

 更新時間:2026年03月12日 09:31:58   作者:在掘金80110  
這篇文章主要介紹了vue3中使用medium-zoom方法的相關資料,Medium Zoom是一個輕量級的JavaScript庫,用于實現(xiàn)類似Medium網站的圖片點擊放大縮放效果,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

簡介

Medium Zoom 是一個輕量級 JavaScript 庫,用于實現(xiàn)類似 Medium 網站的圖片點擊放大縮放效果。本文檔專注于在 Vue3 項目中的集成和使用。

核心特性

  • ?? 響應式設計 - 完美適配移動端和桌面端
  • ?? 高性能 - 優(yōu)化至 60fps 流暢動畫
  • ?? 高清圖支持 - 通過 data-zoom-src 屬性加載高清大圖
  • ?? 可定制化 - 支持自定義邊距、背景、滾動偏移等
  • ?? 事件系統(tǒng) - 完整的生命周期事件監(jiān)聽
  • ?? 零依賴 - 無任何運行時依賴
  • ?? 框架友好 - 完美支持 Vue3 組合式 API

安裝

使用 npm

npm install medium-zoom

使用 yarn

yarn add medium-zoom

使用 pnpm

pnpm add medium-zoom

Vue3 快速開始

方法一:封裝組件(推薦)

創(chuàng)建一個可復用的 ImageZoom.vue 組件:

<script setup lang="ts">
import { watch, type ImgHTMLAttributes, type ComponentPublicInstance } from 'vue'
import mediumZoom, { type Zoom, type ZoomOptions } from 'medium-zoom'

interface Props extends ImgHTMLAttributes {
  options?: ZoomOptions
}

const props = defineProps<Props>()

let zoom: Zoom | null = null

function getZoom() {
  if (zoom === null) {
    zoom = mediumZoom(props.options)
  }
  return zoom
}

function attachZoom(ref: Element | ComponentPublicInstance | null) {
  const image = ref as HTMLImageElement | null
  const zoom = getZoom()

  if (image) {
    zoom.attach(image)
  } else {
    zoom.detach()
  }
}

watch(() => props.options, (options) => {
  const zoom = getZoom()
  zoom.update(options || {})
})
</script>

<template>
  <img :ref="attachZoom" v-bind="$attrs" />
</template>

使用封裝的組件

<script setup lang="ts">
import ImageZoom from './components/ImageZoom.vue'
</script>

<template>
  <article>
    <h1>我的圖片畫廊</h1>

    <!-- 基礎使用 -->
    <ImageZoom src="/images/photo-1.jpg" alt="照片1" />

    <!-- 自定義背景色 -->
    <ImageZoom 
      src="/images/photo-2.jpg" 
      alt="照片2"
      :options="{ background: '#000000' }" 
    />

    <!-- 自定義邊距 -->
    <ImageZoom 
      src="/images/photo-3.jpg" 
      alt="照片3"
      :options="{ margin: 48, background: 'rgba(0,0,0,0.9)' }" 
    />

    <!-- 高清圖支持 -->
    <ImageZoom 
      src="/images/thumbnail.jpg" 
      data-zoom-src="/images/hd-image.jpg"
      alt="高清圖片"
    />
  </article>
</template>

方法二:在 Composable 中使用

創(chuàng)建 useImageZoom.ts

import { onMounted, onUnmounted, ref, type Ref } from 'vue'
import mediumZoom, { type Zoom, type ZoomOptions } from 'medium-zoom'

export function useImageZoom(
  selector?: string | HTMLElement,
  options?: ZoomOptions
) {
  const zoom: Ref<Zoom | null> = ref(null)

  onMounted(() => {
    zoom.value = mediumZoom(selector, options)
  })

  onUnmounted(() => {
    zoom.value?.detach()
  })

  return {
    zoom,
    open: () => zoom.value?.open(),
    close: () => zoom.value?.close(),
    toggle: () => zoom.value?.toggle(),
  }
}

使用 Composable:

<script setup lang="ts">
import { onMounted } from 'vue'
import { useImageZoom } from './composables/useImageZoom'

// 初始化 zoom
const { zoom, open, close } = useImageZoom('[data-zoomable]', {
  margin: 24,
  background: '#BADA55',
})

// 也可以在掛載后動態(tài)附加圖片
onMounted(() => {
  zoom.value?.attach('.gallery-image')
})
</script>

<template>
  <div>
    <img src="/image-1.jpg" data-zoomable alt="圖片1" />
    <img src="/image-2.jpg" data-zoomable alt="圖片2" />
    <img src="/image-3.jpg" class="gallery-image" alt="圖片3" />
    
    <!-- 手動控制按鈕 -->
    <button @click="open">放大第一張圖片</button>
    <button @click="close">關閉縮放</button>
  </div>
</template>

方法三:直接在組件中使用

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import mediumZoom from 'medium-zoom'

const zoomRef = ref(null)

onMounted(() => {
  zoomRef.value = mediumZoom('.zoomable', {
    margin: 24,
    background: '#fff',
    scrollOffset: 40,
  })
})

onUnmounted(() => {
  zoomRef.value?.detach()
})
</script>

<template>
  <div>
    <img src="/image.jpg" class="zoomable" alt="可縮放圖片" />
  </div>
</template>

配置選項 (ZoomOptions)

屬性類型默認值說明
marginnumber0縮放圖片外的空白邊距(像素)
backgroundstring"#fff"遮罩層背景色,支持任何 CSS 顏色值
scrollOffsetnumber40滾動多少像素后自動關閉縮放
containerstring | HTMLElement | objectnull指定縮放渲染的容器視口
templatestring | HTMLTemplateElementnull自定義模板元素

配置示例

const options: ZoomOptions = {
  margin: 48,                    // 48px 邊距
  background: 'rgba(0,0,0,0.9)', // 半透明黑色背景
  scrollOffset: 100,             // 滾動 100px 后關閉
  container: '#zoom-container',  // 在指定容器內縮放
}

API 方法

open(options?: { target?: HTMLElement }): Promise<Zoom>

打開縮放,返回 Promise。

zoom.value?.open()
// 或指定目標圖片
zoom.value?.open({ target: imgElement })

close(): Promise<Zoom>

關閉縮放,返回 Promise。

zoom.value?.close()

toggle(options?: { target?: HTMLElement }): Promise<Zoom>

切換縮放狀態(tài)(打開/關閉)。

zoom.value?.toggle()

attach(...selectors): Zoom

附加圖片到縮放實例。

zoom.value?.attach('#image-1', '#image-2')
zoom.value?.attach(document.querySelector('#image-3'))

detach(...selectors): Zoom

從縮放實例中移除圖片。

zoom.value?.detach('#image-1')
zoom.value?.detach() // 移除所有圖片

update(options: ZoomOptions): Zoom

更新配置選項。

zoom.value?.update({ 
  background: '#000',
  margin: 50 
})

clone(options?: ZoomOptions): Zoom

克隆一個新的縮放實例,合并新配置。

const newZoom = zoom.value?.clone({ margin: 100 })

on(type: string, listener: Function, options?): Zoom

注冊事件監(jiān)聽器。

zoom.value?.on('open', (event) => {
  console.log('圖片已打開', event.detail.zoom)
})

off(type: string, listener: Function, options?): Zoom

移除事件監(jiān)聽器。

const handler = (event) => { /* ... */ }
zoom.value?.on('open', handler)
zoom.value?.off('open', handler)

getOptions(): ZoomOptions

獲取當前配置選項。

const currentOptions = zoom.value?.getOptions()

getImages(): HTMLElement[]

獲取所有已附加的圖片元素。

const images = zoom.value?.getImages()

getZoomedImage(): HTMLElement | null

獲取當前正在縮放的圖片元素。

const currentImage = zoom.value?.getZoomedImage()

事件系統(tǒng)

可用事件

事件名觸發(fā)時機說明
open調用 open() 方法時立即觸發(fā)縮放動畫開始前
opened縮放動畫完成后圖片已完全放大
close調用 close() 方法時立即觸發(fā)關閉動畫開始前
closed關閉動畫完成后圖片已完全縮小
detach調用 detach() 方法時圖片從實例中移除
update調用 update() 方法時配置選項已更新

Vue3 中使用事件

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import mediumZoom from 'medium-zoom'

const zoom = ref(null)
const zoomCount = ref(0)

onMounted(() => {
  zoom.value = mediumZoom('[data-zoomable]')
  
  // 監(jiān)聽打開事件
  zoom.value.on('open', (event) => {
    console.log('開始縮放:', event.target.alt)
  })
  
  // 監(jiān)聽打開完成事件
  zoom.value.on('opened', (event) => {
    zoomCount.value++
    console.log(`已縮放 ${zoomCount.value} 次`)
  })
  
  // 監(jiān)聽關閉事件
  zoom.value.on('close', () => {
    console.log('開始關閉縮放')
  })
  
  // 監(jiān)聽關閉完成事件
  zoom.value.on('closed', () => {
    console.log('縮放已關閉')
  })
  
  // 單次事件監(jiān)聽
  zoom.value.on('open', (event) => {
    console.log('這個只觸發(fā)一次')
  }, { once: true })
})
</script>

<template>
  <div>
    <img src="/image.jpg" data-zoomable alt="圖片" />
    <p>已縮放次數: {{ zoomCount }}</p>
  </div>
</template>

高級用法

1. 高清圖加載

使用 data-zoom-src 屬性指定高清大圖:

<template>
  <ImageZoom 
    src="/thumbnails/small.jpg" 
    data-zoom-src="/images/large-hd.jpg"
    alt="高清圖片"
  />
</template>

2. 在 Markdown 渲染中使用

適用于博客、文檔等場景:

<script setup lang="ts">
import { onMounted, ref, nextTick } from 'vue'
import mediumZoom from 'medium-zoom'
import MarkdownIt from 'markdown-it'

const md = new MarkdownIt()
const content = ref('')
const zoom = ref(null)

const markdown = `
# 我的文章
![圖片1](/image-1.jpg)
![圖片2](/image-2.jpg)
`

onMounted(async () => {
  content.value = md.render(markdown)
  
  await nextTick()
  
  // 為所有 markdown 渲染的圖片添加縮放
  zoom.value = mediumZoom('.markdown-body img', {
    background: 'rgba(255,255,255,0.95)',
    margin: 24
  })
})
</script>

<template>
  <div class="markdown-body" v-html="content"></div>
</template>

3. 自定義容器

在指定容器內縮放:

<script setup lang="ts">
import { onMounted } from 'vue'
import mediumZoom from 'medium-zoom'

onMounted(() => {
  mediumZoom('[data-zoomable]', {
    container: '#custom-container',
    background: 'transparent'
  })
})
</script>

<template>
  <div id="custom-container" style="position: relative; height: 500px;">
    <img src="/image.jpg" data-zoomable alt="圖片" />
  </div>
</template>

4. 動態(tài)添加/移除圖片

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import mediumZoom from 'medium-zoom'

const images = ref(['/img1.jpg', '/img2.jpg'])
const zoom = ref(null)

onMounted(() => {
  zoom.value = mediumZoom('.gallery img')
})

function addImage() {
  const newImg = `/img${images.value.length + 1}.jpg`
  images.value.push(newImg)
  
  // 下一幀后附加新圖片
  nextTick(() => {
    const newElement = document.querySelector(`.img-${images.value.length - 1}`)
    zoom.value?.attach(newElement)
  })
}

function removeImage(index: number) {
  const imgElement = document.querySelector(`.img-${index}`)
  zoom.value?.detach(imgElement)
  images.value.splice(index, 1)
}
</script>

<template>
  <div class="gallery">
    <img 
      v-for="(src, index) in images" 
      :key="index"
      :src="src" 
      :class="`img-${index}`"
      alt="圖片" 
    />
    <button @click="addImage">添加圖片</button>
  </div>
</template>

5. 從外部按鈕觸發(fā)縮放

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import mediumZoom from 'medium-zoom'

const zoom = ref(null)
const imageRef = ref(null)

onMounted(() => {
  zoom.value = mediumZoom(imageRef.value)
})

function handleZoom() {
  zoom.value?.toggle({ target: imageRef.value })
}
</script>

<template>
  <div>
    <img ref="imageRef" src="/image.jpg" alt="圖片" />
    <button @click="handleZoom">點擊縮放圖片</button>
  </div>
</template>

6. 圖片畫廊示例

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import mediumZoom from 'medium-zoom'

const zoom = ref(null)

const gallery = [
  { id: 1, src: '/gallery/img1.jpg', thumb: '/gallery/thumb1.jpg', alt: '風景1' },
  { id: 2, src: '/gallery/img2.jpg', thumb: '/gallery/thumb2.jpg', alt: '風景2' },
  { id: 3, src: '/gallery/img3.jpg', thumb: '/gallery/thumb3.jpg', alt: '風景3' },
]

onMounted(() => {
  zoom.value = mediumZoom('.gallery-image', {
    margin: 48,
    background: '#000',
  })
  
  zoom.value.on('opened', (event) => {
    console.log(`正在查看: ${event.target.alt}`)
  })
})
</script>

<template>
  <div class="gallery-grid">
    <div v-for="item in gallery" :key="item.id" class="gallery-item">
      <img 
        :src="item.thumb" 
        :data-zoom-src="item.src"
        :alt="item.alt"
        class="gallery-image"
      />
      <p>{{ item.alt }}</p>
    </div>
  </div>
</template>

<style scoped>
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

.gallery-image {
  width: 100%;
  cursor: zoom-in;
  transition: opacity 0.3s;
}

.gallery-image:hover {
  opacity: 0.8;
}
</style>

樣式定制

如果需要自定義 z-index(避免與其他 UI 框架沖突):

/* 在全局樣式中添加 */
.medium-zoom-overlay,
.medium-zoom-image--opened {
  z-index: 9999;
}

自定義動畫時長:

.medium-zoom-image--opened {
  transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1);
}

TypeScript 支持

完整的 TypeScript 類型定義:

import mediumZoom, { 
  type Zoom, 
  type ZoomOptions, 
  type ZoomSelector,
  type ZoomOpenOptions 
} from 'medium-zoom'

// Zoom 實例類型
const zoom: Zoom = mediumZoom()

// 配置選項類型
const options: ZoomOptions = {
  margin: 24,
  background: '#fff',
  scrollOffset: 40,
}

// 選擇器類型
const selector: ZoomSelector = '.image' // string | HTMLElement | HTMLElement[] | NodeList

常見問題

Q: 縮放的圖片看不見?

A: 某些 UI 框架可能設置了較高的 z-index,需要手動設置:

.medium-zoom-overlay,
.medium-zoom-image--opened {
  z-index: 9999;
}

Q: 在 v-for 中使用無效?

A: 確保在 DOM 更新后再附加圖片:

<script setup>
import { nextTick } from 'vue'

async function addImages() {
  images.value.push(newImage)
  await nextTick()
  zoom.value?.attach('.new-image')
}
</script>

Q: 如何在路由切換時清理?

A: 使用 onUnmounted 鉤子:

<script setup>
import { onUnmounted } from 'vue'

onUnmounted(() => {
  zoom.value?.detach()
})
</script>

瀏覽器支持

  • Chrome 36+
  • Firefox 34+
  • Safari 9+
  • Edge 12+
  • IE 10+ (需要 template polyfill)

參考資源

提示: 本文檔基于 medium-zoom 庫分析生成,適用于 Vue 3.x 版本項目。

到此這篇關于vue3中使用medium-zoom方法的文章就介紹到這了,更多相關vue3使用medium-zoom內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • vue實現(xiàn)app頁面切換動畫效果實例

    vue實現(xiàn)app頁面切換動畫效果實例

    本篇文章主要介紹了vue實現(xiàn)app頁面切換動畫效果實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • vue實現(xiàn)動態(tài)路由的方法及路由原理解析

    vue實現(xiàn)動態(tài)路由的方法及路由原理解析

    這篇文章主要介紹了路由原理及vue實現(xiàn)動態(tài)路由,Vue Router 提供了豐富的 API,可以輕松地實現(xiàn)路由功能,并支持路由參數、查詢參數、命名路由、嵌套路由等功能,可以滿足不同應用程序的需求,需要的朋友可以參考下
    2023-06-06
  • vue3學習筆記簡單封裝axios示例實現(xiàn)

    vue3學習筆記簡單封裝axios示例實現(xiàn)

    這篇文章主要為大家介紹了vue3學習筆記簡單封裝axios示例實現(xiàn),
    2022-06-06
  • 在uni-app中使用vant組件的方法

    在uni-app中使用vant組件的方法

    最近在做uni-app的時候需要用到vant組件,在網上看到了很多的使用vant組件的方法,但是講解的大多繁瑣,或者無法使用,現(xiàn)把最新,最實用的vant組件的使用方法分享給大家,需要的朋友可以參考下
    2023-02-02
  • Vue中使用ECharts與v-if的問題和解決方案

    Vue中使用ECharts與v-if的問題和解決方案

    在Vue項目中使用v-if指令控制ECharts圖表顯示時,可能會遇到圖表無法正常渲染或顯示錯誤的問題,下面這篇文章主要介紹了Vue中使用ECharts與v-if的問題和解決方案,需要的朋友可以參考下
    2024-10-10
  • 使用 vue 實現(xiàn)滅霸打響指英雄消失的效果附demo

    使用 vue 實現(xiàn)滅霸打響指英雄消失的效果附demo

    這篇文章主要介紹了使用 vue 實現(xiàn)滅霸打響指英雄消失的效果 demo,需要的朋友可以參考下
    2019-05-05
  • 使用Axios攔截器中止Vue請求的步驟詳解

    使用Axios攔截器中止Vue請求的步驟詳解

    假設?App?的用戶可以在短時間內進行多個?API?調用,但您只想顯示上次調用的結果,之前正在進行的請求變得無關緊要,在這種情況下,您可以利用?Axios?攔截器,本文給大家介紹了如何使用Axios攔截器中止Vue請求,需要的朋友可以參考下
    2023-11-11
  • easycom模式開發(fā)UNI-APP組件調用必須掌握的實用技巧

    easycom模式開發(fā)UNI-APP組件調用必須掌握的實用技巧

    uni-app基于VUE開發(fā),通常組件的使用都是先安裝,然后全局或者局部引入,注冊,今天通過本文給大家分享easycom模式開發(fā)UNI-APP組件調用必須掌握的實用技巧,需要的朋友一起看看吧
    2021-08-08
  • vue中formdata傳值給后臺時參數為空的問題

    vue中formdata傳值給后臺時參數為空的問題

    這篇文章主要介紹了vue中formdata傳值給后臺時參數為空的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • vue項目實現(xiàn)分頁效果

    vue項目實現(xiàn)分頁效果

    這篇文章主要為大家詳細介紹了vue項目實現(xiàn)分頁效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03

最新評論

寻乌县| 南宫市| 子长县| 乾安县| 买车| 鄂伦春自治旗| 延长县| 博客| 桓仁| 德令哈市| 栾川县| 广安市| 衢州市| 南陵县| 溧阳市| 白山市| 南汇区| 台南市| 元阳县| 钟山县| 齐河县| 淮北市| 祁连县| 东乡县| 鞍山市| 嵩明县| 岳普湖县| 黎平县| 民县| 洛宁县| 馆陶县| 临桂县| 景洪市| 嘉定区| 乌兰县| 海淀区| 贺州市| 临高县| 武清区| 宁国市| 克拉玛依市|