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' import './style.css' 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() { // 打开完成后,标记为 ready,CSS 此时才会介入 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() }) ) } }