核心原理

无论哪种方法,放大镜的核心原理都离不开以下几点:

网页用js怎么做放大镜
(图片来源网络,侵删)
  1. 三个基本元素:

    • 原图: 用户看到的正常大小的图片。
    • 放大镜区域: 一个在原图上移动的半透明区域,显示放大的部分。
    • 放大图: 一张比原图分辨率高得多(通常是原图的几倍)的图片,作为放大的内容源。
  2. 交互流程:

    • 用户鼠标在 原图 上移动。
    • JavaScript 监听鼠标的坐标。
    • 根据鼠标坐标,在 原图 上显示一个 放大镜区域
    • 放大图 的对应部分移动到 放大镜区域 的位置,从而实现放大效果。

使用 CSS background-position (最常用、最简单)

这种方法利用了 CSS 的 background-position 属性,通过改变背景图片的位置来模拟放大效果,它不需要额外的 HTML 元素来承载放大图,性能较好,实现起来也最简单。

HTML 结构

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">CSS放大镜效果</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="magnifier-container">
        <!-- 原图,作为放大镜的背景 -->
        <img src="https://via.placeholder.com/400x300" alt="原图">
        <!-- 放大镜的镜片 -->
        <div class="magnifier-lens"></div>
        <!-- 放大后的图片显示区域 -->
        <div class="magnifier-result"></div>
    </div>
    <script src="script.js"></script>
</body>
</html>

CSS 样式 (style.css)

关键点:

网页用js怎么做放大镜
(图片来源网络,侵删)
  • .magnifier-container 设置为 position: relative,作为内部元素的定位基准。
  • .magnifier-lens 设置为 position: absolutecursor: none,并设置一个圆形边框和半透明背景。
  • .magnifier-result 设置为 position: absolute,通常放在原图旁边,并设置一个固定大小。
  • 最关键的一步:将原图作为 .magnifier-result 的背景图片,并且通过 background-size 将其放大。
.magnifier-container {
    position: relative;
    display: inline-block;
    margin: 50px;
}
/* 原图样式 */
.magnifier-container img {
    display: block;
    /* 确保图片不会被放大镜覆盖 */
    z-index: 0;
}
/* 放大镜镜片 */
.magnifier-lens {
    position: absolute;
    border: 2px solid #ccc;
    border-radius: 50%; /* 圆形放大镜 */
    cursor: none;
    width: 100px;
    height: 100px;
    background-color: rgba(255, 255, 255, 0.5); /* 半透明 */
    display: none; /* 默认隐藏 */
    z-index: 1;
}
/* 放大后的图片显示区域 */
.magnifier-result {
    position: absolute;
    right: -420px; /* 放在原图右侧 */
    top: 0;
    width: 400px;
    height: 300px;
    border: 1px solid #ccc;
    background-repeat: no-repeat;
    background-color: #fff;
    overflow: hidden; /* 隐藏超出部分 */
    display: none; /* 默认隐藏 */
    z-index: 2;
}

JavaScript 逻辑 (script.js)

逻辑步骤:

  1. 获取所有需要的 DOM 元素。
  2. 定义放大倍数。
  3. 为原图添加 mousemove 事件监听器。
  4. mousemove 事件中:
    • 获取鼠标在图片上的相对坐标。
    • 计算放大镜镜片的位置(left, top)。
    • 限制镜片不能移出图片边界。
    • 设置镜片的显示位置。
    • 核心:计算放大后背景图片的 background-position,这个位置与鼠标位置和放大倍数相关。
document.addEventListener('DOMContentLoaded', () => {
    const container = document.querySelector('.magnifier-container');
    const lens = document.querySelector('.magnifier-lens');
    const result = document.querySelector('.magnifier-result');
    const img = container.querySelector('img');
    // 放大倍数
    const zoom = 3;
    // 1. 当鼠标移入图片区域时,显示放大镜和结果区域
    img.addEventListener('mouseenter', () => {
        lens.style.display = 'block';
        result.style.display = 'block';
    });
    // 2. 当鼠标移出图片区域时,隐藏放大镜和结果区域
    img.addEventListener('mouseleave', () => {
        lens.style.display = 'none';
        result.style.display = 'none';
    });
    // 3. 鼠标在图片上移动时
    img.addEventListener('mousemove', (e) => {
        // 获取图片和容器的位置信息
        const rect = img.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        // 计算放大镜镜片的位置
        // 镜片中心对准鼠标
        let lensX = x - lens.offsetWidth / 2;
        let lensY = y - lens.offsetHeight / 2;
        // 限制镜片不能移出图片边界
        if (lensX < 0) lensX = 0;
        if (lensY < 0) lensY = 0;
        if (lensX > img.offsetWidth - lens.offsetWidth) {
            lensX = img.offsetWidth - lens.offsetWidth;
        }
        if (lensY > img.offsetHeight - lens.offsetHeight) {
            lensY = img.offsetHeight - lens.offsetHeight;
        }
        // 设置镜片的位置
        lens.style.left = `${lensX}px`;
        lens.style.top = `${lensY}px`;
        // --- 核心逻辑:计算背景图片位置 ---
        // 鼠标在图片上的相对位置比例
        const bgX = (x / img.offsetWidth) * 100;
        const bgY = (y / img.offsetHeight) * 100;
        // 设置放大后图片的背景位置
        // background-position 的值需要是负数,并且根据放大倍数进行调整
        // 鼠标在图片中心,背景图片也应该移动到中心,从而让放大的部分显示在结果区域中心
        result.style.backgroundImage = `url(${img.src})`;
        result.style.backgroundSize = `${img.width * zoom}px ${img.height * zoom}px`;
        result.style.backgroundPosition = `${bgX}% ${bgY}%`;
    });
});

使用 <canvas> (更灵活,性能更好)

对于需要高性能处理、或者对图片进行复杂操作(如滤镜、裁剪)的场景,使用 canvas 是更好的选择,它直接操作像素,可以实现更流畅的放大效果。

HTML 结构

<div class="canvas-magnifier-container">
    <img id="canvas-img" src="https://via.placeholder.com/400x300" alt="原图">
    <canvas id="magnifier-canvas"></canvas>
</div>

CSS 样式

.canvas-magnifier-container {
    position: relative;
    display: inline-block;
    margin: 50px;
}
#canvas-img {
    display: block;
}
#magnifier-canvas {
    position: absolute;
    border: 2px solid #ccc;
    border-radius: 50%;
    pointer-events: none; /* 让鼠标事件穿透到下面的img */
    display: none;
}

JavaScript 逻辑

  1. 获取原图和 canvas 元素。
  2. 设置放大镜的尺寸和放大倍数。
  3. mousemove 事件中:
    • 获取鼠标坐标。
    • 创建一个临时的 canvas 来绘制原图。
    • 使用 ctx.drawImage() 的裁剪和缩放功能,只绘制鼠标周围的一小块区域,并将其放大到放大镜 canvas 的整个尺寸上。
document.addEventListener('DOMContentLoaded', () => {
    const img = document.getElementById('canvas-img');
    const magnifierCanvas = document.getElementById('magnifier-canvas');
    const ctx = magnifierCanvas.getContext('2d');
    // 设置放大镜尺寸
    const lensSize = 100;
    magnifierCanvas.width = lensSize;
    magnifierCanvas.height = lensSize;
    // 放大倍数
    const zoom = 3;
    img.addEventListener('mouseenter', () => {
        magnifierCanvas.style.display = 'block';
    });
    img.addEventListener('mouseleave', () => {
        magnifierCanvas.style.display = 'none';
    });
    img.addEventListener('mousemove', (e) => {
        const rect = img.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        // 计算放大镜位置
        let lensX = x - lensSize / 2;
        let lensY = y - lensSize / 2;
        // 边界检查
        if (lensX < 0) lensX = 0;
        if (lensY < 0) lensY = 0;
        if (lensX > img.offsetWidth - lensSize) {
            lensX = img.offsetWidth - lensSize;
        }
        if (lensY > img.offsetHeight - lensSize) {
            lensY = img.offsetHeight - lensSize;
        }
        magnifierCanvas.style.left = `${lensX}px`;
        magnifierCanvas.style.top = `${lensY}px`;
        // --- Canvas 核心逻辑 ---
        // 清除画布
        ctx.clearRect(0, 0, lensSize, lensSize);
        // 计算要裁剪的区域大小
        const sourceSize = lensSize / zoom;
        // 使用 drawImage 的裁剪和缩放功能
        // ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
        // sx, sy: 源图片裁剪的起始坐标
        // sWidth, sHeight: 源图片裁剪的尺寸
        // dx, dy: 在画布上绘制的起始坐标
        // dWidth, dHeight: 在画布上绘制的尺寸
        ctx.drawImage(
            img,
            x - sourceSize / 2, y - sourceSize / 2, // 从鼠标周围裁剪
            sourceSize, sourceSize,                 // 裁剪一小块
            0, 0,                                   // 从画布(0,0)开始绘制
            lensSize, lensSize                      // 绘制到整个放大镜画布上
        );
    });
});

使用第三方库 (最快捷)

如果你只是想快速实现一个功能完善的放大镜,不想自己写代码,使用成熟的库是最好的选择。

一个非常流行的库是 jQuery.zoom,它非常轻量且易于使用。

网页用js怎么做放大镜
(图片来源网络,侵删)

步骤

  1. 引入 jQuery 和 jQuery.zoom:

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-zoom/1.7.21/jquery.zoom.min.js"></script>
  2. HTML 结构:

    <div id="zoom-container">
        <img id="zoom-img" src="https://via.placeholder.com/400x300" data-zoom-image="https://via.placeholder.com/1200x900" alt="原图">
    </div>
  3. JavaScript 调用:

    $(document).ready(function(){
        $('#zoom-img').zoom({
            on: 'hover', // 触发方式: 'hover' 或 'click'
            magnify: 1.5 // 放大倍数
        });
    });

这个库会自动为你处理所有细节,包括创建放大镜区域、处理移动逻辑等,如果你的项目已经使用了 jQuery,这无疑是最高效的选择。

总结与选择建议

方法 优点 缺点 适用场景
CSS background-position 实现简单,代码量少,性能较好,不依赖库。 需要准备一张高分辨率的放大图,不够灵活。 绝大多数标准放大镜需求,是首选方案。
<canvas> 性能最好,非常灵活,可对图片进行像素级操作。 代码逻辑相对复杂,需要理解 canvas API。 对性能要求高、需要动态处理图片(如电商商品图)的场景。
第三方库 最快,功能稳定,开箱即用。 引入了额外的库,增加了项目体积,可能不满足高度定制化需求。 快速开发、项目已使用 jQuery、不想自己造轮子时。

对于初学者和大多数项目,强烈推荐方法一(CSS background-position,它完美地平衡了简单性、性能和效果。