Use Medium-Zoom in Hexo Blog

Use Medium-Zoom in Hexo Blog

Intro

Environment Info

Framework: Hexo
Theme: Icarus

Icarus主题对图片处理时使用 wrap 方法将图片用<a>标签包裹、href(hypertext reference)设为图片的 src,这样点击图片时会跳转到图片的原图地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
// File: main.js
(function($, moment, ClipboardJS, config) {
    $('.article img:not(".not-gallery-item")').each(function() {
        // wrap images with link and add caption if possible
        if ($(this).parent('a').length === 0) {
            $(this).wrap('<a class="gallery-item" href="' + $(this).attr('src') + '"></a>');
            if (this.alt) {
                $(this).after('<p class="has-text-centered is-size-6 caption">' + this.alt + '</p>');
            }
        }
    });
    ......
}(jQuery, window.moment, window.ClipboardJS, window.IcarusThemeSettings));

使用 href 链接会导致网页的跳转,在移动端体验不佳,电脑端差强人意。在Icarus的Github Issue中有人提出了这个问题,为了增强用户点击图片后的交互体验,我们可以使用medium-zoom这一轻量级库,medium-zoom 在点击图片时会在当前页面内创建一个平滑的放大效果,提供更优的视觉体验,查看图片的体验也更直观&沉浸,

BeforeAfter

Steps

  • 引入medium-zoom,以Icarus为例,可以在layout.jsx添加如下代码
    <script src="https://cdn.jsdelivr.net/npm/medium-zoom@latest/dist/medium-zoom.min.js"></script>
  • main.js初始化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // File: Main.js    
    (function($, moment, ClipboardJS, config) {
    -   $('.article img:not(".not-gallery-item")').each(function() {
    -       // wrap images with link and add caption if possible
    -       if ($(this).parent('a').length === 0) {
    -           $(this).wrap('<a class="gallery-item" href="' + $(this).attr('src') + '"></a>');
    -           if (this.alt) {
    -               $(this).after('<p class="has-text-centered is-size-6 caption">' + this.alt + '</p>');
    -           }
    -       }
    -   });
        ......
    +    document.addEventListener("DOMContentLoaded", function () {
    +        mediumZoom('.article img', {
    +            background: 'rgba(30, 30, 46, 0.5)',
    +        });
    +    });
    }(jQuery, window.moment, window.ClipboardJS, window.IcarusThemeSettings));
  • 根据个人喜好,添加相应样式。建议调整 z-index 以确保放大后的图片在最上层。此外,可通过利用backdrop-filter实现模糊效果
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    .medium-zoom-overlay {
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      z-index: 9998 !important;
    }
    
    
    img.medium-zoom-image {
        border-radius: 5px;
    }
    
    .medium-zoom-image--opened {
        z-index: 9999;
        position: fixed;
    }

FAQ

部分图片放大后位置不在可视页面内

目前遇到这些问题的图片,都设置了zoom属性,CSS 中的 zoom 属性并非 W3C 标准,可能导致 medium-zoom 计算图片尺寸的位置出现偏差,从而影响图片居中和放大效果。
解决方案就是换用标准的 CSS 属性(如 width)来控制图片大小,VSCode中可以用Ctrl+Shift+H批量替换

1
2
- <img src="example.jpg" style="zoom:30%;" alt="示例图片">
+ <img src="example.jpg" style="width:30%;" alt="示例图片">

PJAX 等异步加载机制导致的初始化问题

Hexo 一些主题(例如 Icarus)时,多采用 PJAX 或局部刷新加载页面。对于使用 PJAX 或异步加载的博客页面,需要在内容更新后重新初始化 medium-zoom。假设使用 PJAX,可以在 PJAX 完成事件中重新调用 mediumZoom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// File: pjax.js
document.addEventListener('pjax:complete', () => {
    // Plugin [MathJax] reload logic
    if (window.MathJax) {
        try {
            window.MathJax.typesetPromise && window.MathJax.typesetPromise();
        } catch (e) {
            console.error('MathJax reload error:', e);
        }
    }
+   mediumZoom('.article img', {
+       background: 'rgba(30, 30, 46, 0.5)',
+   });
    // TODO pace stop loading animation
});
作者

GnixAij

发布于

2025-02-23

更新于

2025-03-09

许可协议

评论