前言

Vuepress默认的图片浏览是点击放大,可以说是非常简洁,如果网站图片比较多,还是可以加载Fancybox来使它更加优雅。

因为我不喜欢把一大堆包都放在服务器,直接从CDN引入,自动加载其最新版本,这样省去很多后期维护成本。

这篇文章介绍一下这种最简单的方法让Vuepress网站使用Fancybox。

图片步骤(已验证)

  1. 创建fancybox插件

    docs/.vuepress/plugins 目录中创建一个名为vuepress-plugin-fancybox 的目录,如果没有 plugins 目录,先创建此目录;

    vuepress-plugin-fancybox 目录下,添加名为 index.js 的文件,将下面内容添加进去:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // docs/.vuepress/plugins/vuepress-plugin-fancybox/index.js
    export default () => ({
    name: 'vuepress-plugin-fancybox',
    extendsMarkdown(md) {
    md.renderer.rules.image = function (tokens, idx, options, env, self) {
    const token = tokens[idx]
    const srcIndex = token.attrIndex('src')
    const src = token.attrs[srcIndex][1]
    const alt = token.content || ''
    // 使用页面路径作为 gallery 名称,避免跨页面冲突
    const galleryName = (env.relativePath || 'gallery')
    .replace(/\//g, '-')
    .replace(/\.\w+$/, '')
    return `<a href="${src}" data-fancybox="${galleryName}"><img src="${src}" alt="${alt}"></a>`
    }
    },
    })
  2. 修改 docs/.vuepress/config.js 配置文件

    对应栏目添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    // docs/.vuepress/config.js
    import { viteBundler } from '@vuepress/bundler-vite'
    import { defaultTheme } from '@vuepress/theme-default'
    //..省略..//
    import fancyboxPlugin from './plugins/vuepress-plugin-fancybox/index.js'

    export default defineUserConfig({

    //..省略..//

    head: [
    ['link', { rel: 'stylesheet', href: 'https://unpkg.com/@fancyapps/ui/dist/fancybox/fancybox.css' }],
    ['script', { src: 'https://unpkg.com/@fancyapps/ui/dist/fancybox/fancybox.umd.js' }],
    ['script', {}, `
    document.addEventListener('DOMContentLoaded', () => {
    if (window.Fancybox) {
    window.Fancybox.bind('[data-fancybox]');
    }
    });
    `],

    //..省略..//

    ],

    //..省略..//

    plugins: [
    fancyboxPlugin(),

    //..省略..//

    ],
    })
  3. 构建网站

    最后使用 npm run docs:build 或者 npm run docs:dev 进行调试。

同时处理图片以及视频(未验证)

Fancybox给我最大的亮点是使用下面代码可以播放视频:

1
2
3
<a href="/sample.mp4" data-fancybox data-width="640" data-height="360">
<img src="/poster.jpg" alt="Video poster" width="240" height="180" />
</a>

提供一个思路,修改 docs/.vuepress/plugins/vuepress-plugin-fancybox/index.js 的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// docs/.vuepress/plugins/vuepress-plugin-fancybox/index.js
export default () => ({
name: 'vuepress-plugin-fancybox',

extendsMarkdown(md) {
md.renderer.rules.image = function (tokens, idx, options, env, self) {
const token = tokens[idx]
const srcIndex = token.attrIndex('src')
const src = token.attrs[srcIndex][1]
const alt = token.content || ''

const galleryName = (env.relativePath || 'gallery')
.replace(/\//g, '-')
.replace(/\.\w+$/, '')

// 判断是否是视频
const isVideo = /\.(mp4|webm|ogg)$/i.test(src)

if (isVideo) {
// 动态计算屏幕尺寸
const width = window.innerWidth * 0.8 // 自适应 80% 屏幕宽度
const height = window.innerHeight * 0.8 // 自适应 80% 屏幕高度

return `<a href="${src}" data-fancybox="${galleryName}" data-width="${width}" data-height="${height}">
<img src="${token.attrs[srcIndex][1]}" alt="${alt}" />
</a>`
}

// 默认渲染图片
return `<a href="${src}" data-fancybox="${galleryName}"><img src="${src}" alt="${alt}"></a>`
}
},
})

不想弄视频的原因是需要给每个视频添加缩略图啥的,太麻烦,而且要考虑markdown的书写方式,图片和视频怎么写,怎么判断它是超链接还是图片,还是视频,缩略图怎么加,我这边也只是给个大致方向。不管出于什么原因,都不建议把视频加上。

最后

要说一个比较让我有点不习惯的地方:比如一个网页有很多图片,通过Fancybox浏览到其他一张图片,在这个位置关掉图片,那么页面会自动滚动到此时图片所在的位置。

不过这个也可以进行关闭:

1
2
3
4
5
6
7
8
9
10
// docs/.vuepress/config.js
['script', {}, `
document.addEventListener('DOMContentLoaded', () => {
if (window.Fancybox) {
window.Fancybox.bind('[data-fancybox]', {
placeFocusBack: false //添加这个
});
}
});
`],

其他的完全没问题。