﻿---
title: Use Medium-Zoom in Hexo Blog
date: 2025-02-23
excerpt: 在 Hexo Blog中，为了增强用户点击图片后的交互体验，我们可以使用medium-zoom这一轻量级库实现图片放大效果。本文记录如何在 Hexo 博客中成功集成 medium-zoom
tags: [Hexo, Icarus, Web, Blog, Pjax]
cover: https://assets.vluv.space/cover/FrontEnd/medium-zoom.webp
---

## Intro

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

```js
// 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](<(https://github.com/ppoffice/hexo-theme-icarus/issues/868)>)中有人提出了这个问题，为了增强用户点击图片后的交互体验，我们可以使用[medium-zoom](https://github.com/francoischalifour/medium-zoom)这一轻量级库，medium-zoom 在点击图片时会在当前页面内创建一个平滑的放大效果，提供更优的视觉体验，查看图片的体验也更直观&沉浸，

| Before                                                                                                                    | After                                                                                                                    |
| ------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| <video autoplay loop muted playsinline><source src="https://assets.vluv.space/medium_zoom1.mp4" type="video/mp4"></video> | <video autoplay loop muted playsinline><source src="https://assets.vluv.space/medium-zoom.mp4" type="video/mp4"></video> |

## Steps

- 引入`medium-zoom`，以 Icarus 为例，可以在`layout.jsx`添加如下代码
  `{html} <script src="https://cdn.jsdelivr.net/npm/medium-zoom@latest/dist/medium-zoom.min.js"></script>`
- 在`main.js`初始化

  ```js main.js
  (function($, moment, ClipboardJS, config) {
     $('.article img:not(".not-gallery-item")').each(function() { // [!code --]
         // wrap images with link and add caption if possible // [!code --]
         if ($(this).parent('a').length === 0) { // [!code --]
             $(this).wrap('<a class="gallery-item" href="' + $(this).attr('src') + '"> </a>'); // [!code --]
             if (this.alt) { // [!code --]
                 $(this).after('<p class="has-text-centered is-size-6 caption">' + this.alt  + '</p>'); // [!code --]
             } // [!code --]
         } // [!code --]
     }); // [!code --]
      ......
      document.addEventListener("DOMContentLoaded", function () { // [!code ++]
          mediumZoom('.content img', { // [!code ++]
              background: 'rgba(30, 30, 46, 0.5)', // [!code ++]
          }); // [!code ++]
      }); // [!code ++]
  }(jQuery, window.moment, window.ClipboardJS, window.IcarusThemeSettings));
  ```

- 根据个人喜好，添加相应样式。建议调整 z-index 以确保放大后的图片在最上层。此外，可通过利用`backdrop-filter`实现模糊效果

  ```css
  .medium-zoom-overlay {
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    z-index: 150 !important;
  }

  .medium-zoom-image--opened {
    z-index: 151;
    position: fixed;
  }
  ```

## Q&A

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

目前遇到这些问题的图片，都使用了`style="zoom: 30%"`[^1]来控制缩放，但这与 medium-zoom 存在兼容性问题，导致放大后的图片位置偏移，无法居中显示。 解决方法是将`zoom`属性替换为`width: 30%`或使用`transform: scale(0.3)`来实现缩放效果。

### PJAX Issue

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

```js
document.addEventListener('pjax:complete', () => {
    mediumZoom('.content img', {
        background: 'rgba(30, 30, 46, 0.5)',
    });
    // TODO pace stop loading animation
});
```

[^1]: [zoom | CSS-Tricks](https://css-tricks.com/almanac/properties/z/zoom/)