Files
test-repo/docs/.vitepress/theme/index.js
T

128 lines
3.8 KiB
JavaScript
Raw Normal View History

import DefaultTheme from 'vitepress/theme'
import Viewer from 'viewerjs'
import 'viewerjs/dist/viewer.css'
import TypeIt from 'typeit'
import { onMounted, watch, nextTick } from 'vue'
import { useRoute, useData } from 'vitepress'
export default {
extends: DefaultTheme,
setup() {
const route = useRoute()
const { frontmatter } = useData()
let viewer = null
const initViewer = () => {
// 销毁旧实例
if (viewer) {
viewer.destroy()
viewer = null
}
// 找到文章内容容器
const doc = document.querySelector('.vp-doc')
if (doc) {
// 初始化 Viewer,配置一些常用选项
viewer = new Viewer(doc, {
button: true, // 显示右上角关闭按钮
navbar: true, // 显示底部缩略图导航
title: true, // 显示图片标题(alt 属性)
toolbar: true, // 显示工具栏(缩放、旋转等)
tooltip: true, // 显示缩放百分比
movable: true, // 允许拖拽
zoomable: true, // 允许缩放
rotatable: true, // 允许旋转
scalable: true, // 允许翻转
transition: false, // 禁用自带动画,确保打开瞬间无飞入
fullscreen: true, // 允许全屏播放
shown() {
// 打开完成后,标记为 readyCSS 此时才会介入 transition
document.body.classList.add('viewer-ready')
},
hide() {
// 关闭前移除标记,确保关闭瞬间无动画
document.body.classList.remove('viewer-ready')
},
keyboard: true, // 允许键盘控制
url: 'src', // 图片源
// 过滤掉不想查看的图片(比如表情包等小图标,如果需要的话)
filter(image) {
return !image.classList.contains('no-viewer')
}
})
}
}
const initTypewriter = () => {
const taglineData = frontmatter.value.hero?.tagline
if (Array.isArray(taglineData) && taglineData.length > 0) {
const taglineEl = document.querySelector('.VPHomeHero .tagline')
if (taglineEl) {
taglineEl.innerHTML = ''
const typeIt = new TypeIt(taglineEl, {
speed: 50,
startDelay: 500,
loop: true
})
taglineData.forEach((text) => {
typeIt.type(text).pause(2000).delete().pause(500)
})
typeIt.go()
}
}
}
const optimizeImages = () => {
const images = document.querySelectorAll('.vp-doc img')
images.forEach(img => {
if (img.complete) {
applyImageStyle(img)
} else {
img.onload = () => applyImageStyle(img)
}
})
}
const applyImageStyle = (img) => {
const { naturalWidth, naturalHeight } = img
if (!naturalWidth || !naturalHeight) return
const ratio = naturalHeight / naturalWidth
img.classList.remove('img-tall', 'img-very-tall', 'img-ultra-tall')
img.style.width = 'auto' // 确保宽度自动,防止拉伸
if (ratio > 3) {
img.classList.add('img-ultra-tall')
img.style.maxHeight = '250px'
} else if (ratio > 2) {
img.classList.add('img-very-tall')
img.style.maxHeight = '350px'
} else if (ratio > 1.2) {
img.classList.add('img-tall')
img.style.maxHeight = '450px'
} else {
// 普通图片重置,避免复用 dom 时残留样式
img.style.maxHeight = ''
}
}
onMounted(() => {
initViewer()
initTypewriter()
optimizeImages()
})
watch(
() => route.path,
() => nextTick(() => {
initViewer()
initTypewriter()
optimizeImages()
})
)
}
}