Skip to content

给VitePress增加图片缩放功能

演示

image.png

安装medium-zoom

sh
npm i -D medium-zoom

第一步、引入库以及配置相关文件

新建docs/.vitepress/theme/index.ts,在对应位置引入medium-zoom库与全局样式

ts
import DefaultTheme from 'vitepress/theme'
import { onMounted, watch, nextTick } from 'vue'
import { useRoute } from 'vitepress'
import mediumZoom from 'medium-zoom'
import './global.css'

export default {
  extends: DefaultTheme,
  setup() {
    const route = useRoute()
    const initZoom = () => {
      // 为所有图片增加缩放功能
      mediumZoom('.main img', { background: 'var(--vp-c-bg)' })
    }
    onMounted(() => {
      initZoom()
    })
    watch(
      () => route.path,
      () => nextTick(() => initZoom())
    )
  }
}

这时候,点击图片放大的功能已经实现了,会出现被侧边栏遮挡的情况,所以需要修改全局样式

新建docs/.vitepress/theme/global.css,添加如下样式代码,然后在docs/.vitepress/theme/index.ts引入它

css
.medium-zoom-overlay {
  background-color: var(--vp-c-bg) !important;
  z-index: 100;
}

.medium-zoom-overlay ~ img {
  z-index: 101;
}

.medium-zoom--opened .medium-zoom-overlay {
  opacity: 0.9 !important;
}

第二步、自定义MarkDown图片渲染插件

新建docs/.vitepress/plugins/markdown/image.ts,添加如下代码

ts
import type MarkdownIt from 'markdown-it'
export function ImagePlugin(md: MarkdownIt) {
  const imageRender = md.renderer.rules.image! // 尾部的这个感叹号的意思是断言此变量肯定有值
  md.renderer.rules.image = (...args) => {
    const [tokens, idx] = args
    if (tokens[idx + 2] && /^<!--.*-->/.test(tokens[idx + 2].content)) {
      const data = tokens[idx + 2].content
      if (/size=/.test(data)) {
        const size = data.match(/size=(\d+)(x\d+)?/)
        tokens[idx].attrs?.push(
          ['width', size?.[1] || ''],
          ['height', size?.[2]?.substring(1) || size?.[1] || '']
        )
      }

      tokens[idx].attrs?.push(['loading', 'lazy'], ['decoding', 'async'])
      tokens[idx + 2].content = ''
      return imageRender(...args)
    }
    tokens[idx].attrs?.push(['loading', 'lazy'], ['decoding', 'async'])
    return imageRender(...args)
  }
}

编辑docs/.vitepress/config.ts

ts
import { ImagePlugin } from './plugins/markdown/image'
export default defineConfig({
  // ...
  markdown: {
    config: (md) => {
      md.use(ImagePlugin) 
    },
  },
})