MENU

为 Vuepress 增加图片放大功能的几种方法

2020 年 07 月 30 日 • 阅读: 24616 • 前端

Vuepress 文档中引入图片时,由于某些图片内容密集,必须放大才能看清。虽然可以通过拆分图片解决,但不免有些麻烦。搜索后发现,社区中有两种方案与此相关。其一是 medium-zoom 插件,它虽然支持放大,但默认占满全屏,无法手动调节倍数。另一种是引入 fancybox,它支持倍数调节,为此有人专门编写了 VSCode 插件,通过快捷键,转换当前 Markdown 文件里的图片标签。这种方式也有缺点,不仅要逐个文件手动转换,而且不符合 Markdown 语法。

由此便确立了目标,通过 Vuepress 的某种机制,自动 将文件里的 Markdown 图片标签转为 fancybox 可识别的 a 标签。

运行时

查阅文档后发现,可以将插件代码注入 Vuepress 生命周期,在浏览器端扫描图片标签并转换。

具体实现如下:首先新建 docs/.vuepress/plugins/fancybox/mixin.js 文件,写入如下代码:

  • export default {
  • mounted() {
  • this.update();
  • },
  • updated() {
  • this.update();
  • },
  • methods: {
  • update() {
  • document.querySelectorAll("p>img").forEach(img => {
  • img.parentElement.innerHTML = `<a data-fancybox href="${img.src}" content="${img.alt}">${img.outerHTML}</a>`;
  • });
  • }
  • }
  • };

随后,在相同文件夹下新建 index.js 文件写入如下代码:

  • const { path } = require("@vuepress/shared-utils");
  • module.exports = (options, ctx) => ({
  • clientRootMixin: path.resolve(__dirname, "mixin.js")
  • });

最后,在 docs/.vuepress/config.js 中引入 插件 和必要的 jscss 文件。

  • const STATIC_CDN = '//s0.pstatp.com/cdn/expire-1-M/'
  • module.exports = {
  • head: [
  • ['script', { src: STATIC_CDN + 'jquery/3.4.0/jquery.min.js' }],
  • ['script', { src: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.js' }],
  • ['link', { rel: 'stylesheet', href: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.css' }]
  • ],
  • plugins: [require('./plugins/fancybox')],
  • }

编译时

另一种方法是在编译期完成上述步骤,方法是编写 Markdown 插件 改变渲染规则,注入 fancybox 标签。但是由于相对路径的图片会被 Webpack 重新打包,而这发生在 Markdown 渲染之后,造成路径错误。因此必须修改 Webpackvue-loader,让其把 fancybox 标签的 src 属性一并改变。具体编码如下:

首先新建 docs/.vuepress/plugins/fancybox/index.js 文件,写入如下代码:

  • const PUBLIC_PREFIX = "/docs/.vuepress/public";
  • module.exports = md => {
  • md.renderer.rules.image = (tokens, idx) => {
  • const token = tokens[idx];
  • const srcIndex = token.attrIndex("src");
  • const url = token.attrs[srcIndex][1].replace(PUBLIC_PREFIX, "");
  • const caption = md.utils.escapeHtml(token.content);
  • return `<a data-fancybox href="${url}" content="${caption}">
  • <img src="${url}" alt="${caption}" />
  • </a>`;
  • };
  • };
  • module.exports.webpack = (config, isServer) => {
  • const inlineLimit = 10000;
  • config.module
  • .rule("images")
  • .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
  • .use("url-loader")
  • .loader("url-loader")
  • .options({
  • limit: inlineLimit,
  • name: `assets/img/[name].[hash:8].[ext]`
  • });
  • config.module
  • .rule("vue")
  • .uses.store.get("vue-loader")
  • .store.get("options").transformAssetUrls = {
  • video: ["src", "poster"],
  • source: "src",
  • img: "src",
  • image: ["xlink:href", "href"],
  • a: "href"
  • };
  • };

随后在 docs/.vuepress/config.js 中引入插件。

  • const STATIC_CDN = '//s0.pstatp.com/cdn/expire-1-M/'
  • module.exports = {
  • head: [
  • ['script', { src: STATIC_CDN + 'jquery/3.4.0/jquery.min.js' }],
  • ['script', { src: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.js' }],
  • ['link', { rel: 'stylesheet', href: STATIC_CDN + 'fancybox/3.5.7/jquery.fancybox.min.css' }]
  • ],
  • markdown: {
  • extendMarkdown: md => md.use(require('./plugin/fancybox'))
  • },
  • chainWebpack: require('./plugin/fancybox').webpack
  • }

使用 Vue 组件

上面两种方法都要手动引入 jscss。如需使用 npm 包,可编写单独的 Vue 组件,直接在 Markdown 中引入。不过那样,VSCode 将无法直接预览。

此外,对于处于 docs/.vuepress/public/ 目录中的文件,Webpack 不会重新打包。并且,它是 Vuepress 静态资源的默认根路径,比如 docs/.vuepress/public/1.jpgMarkdown 中写成 /1.jpg 才能被 Vuepress 找到。

我们编写文档时,通常都是以 docs 上级作为项目目录,这将导致 VSCode 无法本地预览。通过使用上文提到的第二种方式,我们可以在 Markdown 中编写正常路径,比如 docs/.vuepress/public/1.jpg,在编译时通过插件将前缀去掉,保证本地预览和编译的正确性。

最后,第二种方式还扩充了相对路径中 Webpack 可识别的 webp 图片格式。即,文档中可引入 md 同级目录下的 webp 图片。具体规则见方式二代码。

TG 大佬群 QQ 大佬群

最后编辑于: 2021 年 10 月 15 日
返回文章列表 文章二维码
本页链接的二维码
打赏二维码
添加新评论

Loading captcha...

  • OωO
  • |´・ω・)ノ
  • ヾ(≧∇≦*)ゝ
  • (☆ω☆)
  • (╯‵□′)╯︵┴─┴
  •  ̄﹃ ̄
  • (/ω\)
  • ∠( ᐛ 」∠)_
  • (๑•̀ㅁ•́ฅ)
  • →_→
  • ୧(๑•̀⌄•́๑)૭
  • ٩(ˊᗜˋ*)و
  • (ノ°ο°)ノ
  • (´இ皿இ`)
  • ⌇●﹏●⌇
  • (ฅ´ω`ฅ)
  • (╯°A°)╯︵○○○
  • φ( ̄∇ ̄o)
  • ヾ(´・ ・`。)ノ"
  • ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
  • (ó﹏ò。)
  • Σ(っ °Д °;)っ
  • ( ,,´・ω・)ノ"(´っω・`。)
  • ╮(╯▽╰)╭
  • o(*////▽////*)q
  • >﹏<
  • ( ๑´•ω•) "(ㆆᴗㆆ)
  • (。•ˇ‸ˇ•。)
  • 泡泡
  • 阿鲁
  • 蛆音娘
  • 小埋
  • 颜文字

已有 5 条评论
  1. 强调几点:(该留言由系统自动生成!)
    1. 请不要刷广告,本站没有流量!
    2. 我不回复虚假邮箱,因为回复了你也看不到!
    3. 存在必须回复的隐藏内容时,可以直接使用表情框里的阿鲁表情!

  1. 小白 小白   Windows 10 x64 Edition  Google Chrome 93.0.4577.82

    markdown-it-remove-image-path-prefix 这个是怎么引入的?

    1. LOGI LOGI   Windows 10 x64 Edition  Google Chrome 94.0.4606.81

      @小白忘改了,应该改成 plugins 下创建的文件夹名,文章里是 fancybox

  2. yiyou yiyou   Windows 10 x64 Edition  Google Chrome 86.0.4240.75

    效果有了,图片并没有放大啊,和原来一样大

    1. LOGI LOGI   Windows 10 x64 Edition  Google Chrome 87.0.4280.88

      @yiyoufancybox 是放大到原始大小,下面的库可以任意缩放,你自己改改
      https://github.com/fengyuanchen/viewerjs

  3. fds fds   Windows 10 x64 Edition  Google Chrome 86.0.4240.111