您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# JS实现图片放大镜效果的脚本怎么写
图片放大镜是电商网站、图库平台常见的交互功能,它能让用户在鼠标悬停时局部放大图片细节。本文将详细介绍如何使用原生JavaScript实现这一效果,涵盖原理分析、代码实现和优化方案。
## 一、放大镜效果的核心原理
放大镜效果的实现主要依赖以下三个技术要点:
1. **层叠布局结构**:
- 原图容器(显示基础图片)
- 放大镜遮罩(半透明选择框)
- 放大结果容器(显示放大后的区域)
2. **坐标映射计算**:
- 鼠标位置 → 遮罩位置
- 遮罩位置 → 放大区域位置
3. **图像比例关系**:
```javascript
放大比例 = 大图宽度 / 原图宽度
<div class="magnifier-container">
<!-- 原图容器 -->
<div class="original-img">
<img src="product.jpg" id="sourceImg" alt="商品图">
<!-- 放大镜遮罩 -->
<div class="magnifier-lens"></div>
</div>
<!-- 放大结果容器 -->
<div class="magnifier-result"></div>
</div>
.magnifier-container {
display: flex;
gap: 20px;
}
.original-img {
position: relative;
width: 400px;
height: 400px;
border: 1px solid #ddd;
overflow: hidden;
}
.magnifier-lens {
position: absolute;
width: 150px;
height: 150px;
background: rgba(255, 255, 255, 0.3);
border: 1px solid #ccc;
cursor: none;
display: none;
}
.magnifier-result {
width: 400px;
height: 400px;
border: 1px solid #ddd;
background-repeat: no-repeat;
display: none;
}
const sourceImg = document.getElementById('sourceImg');
const lens = document.querySelector('.magnifier-lens');
const result = document.querySelector('.magnifier-result');
// 使用大图URL(建议预加载)
const largeImgUrl = 'product-large.jpg';
let largeImg = new Image();
largeImg.src = largeImgUrl;
// 比例计算
const ratio = largeImg.width / sourceImg.width;
sourceImg.addEventListener('mouseenter', () => {
lens.style.display = 'block';
result.style.display = 'block';
// 设置放大镜尺寸
const lensSize = Math.min(
sourceImg.width / 2,
sourceImg.height / 2,
200
);
lens.style.width = `${lensSize}px`;
lens.style.height = `${lensSize}px`;
});
sourceImg.addEventListener('mousemove', (e) => {
const containerRect = sourceImg.getBoundingClientRect();
// 计算鼠标相对位置
let x = e.clientX - containerRect.left;
let y = e.clientY - containerRect.top;
// 边界检测
x = Math.max(lens.offsetWidth/2, Math.min(x, sourceImg.width - lens.offsetWidth/2));
y = Math.max(lens.offsetHeight/2, Math.min(y, sourceImg.height - lens.offsetHeight/2));
// 定位放大镜
lens.style.left = `${x - lens.offsetWidth/2}px`;
lens.style.top = `${y - lens.offsetHeight/2}px`;
// 计算放大图位置
const bgX = (x - lens.offsetWidth/2) * ratio * -1;
const bgY = (y - lens.offsetHeight/2) * ratio * -1;
// 应用放大效果
result.style.backgroundImage = `url(${largeImgUrl})`;
result.style.backgroundSize = `${sourceImg.width * ratio}px ${sourceImg.height * ratio}px`;
result.style.backgroundPosition = `${bgX}px ${bgY}px`;
});
sourceImg.addEventListener('mouseleave', () => {
lens.style.display = 'none';
result.style.display = 'none';
});
// 添加触摸事件支持
sourceImg.addEventListener('touchmove', (e) => {
e.preventDefault();
const touch = e.touches[0];
const mouseEvent = new MouseEvent('mousemove', {
clientX: touch.clientX,
clientY: touch.clientY
});
sourceImg.dispatchEvent(mouseEvent);
});
// 使用requestAnimationFrame优化
let lastTime = 0;
sourceImg.addEventListener('mousemove', (e) => {
const now = Date.now();
if (now - lastTime < 16) return; // 60fps限制
lastTime = now;
// ...原有处理逻辑...
});
// 大图预加载
largeImg.onload = function() {
console.log('大图加载完成');
ratio = largeImg.width / sourceImg.width;
};
function initMagnifier(newImgUrl, newLargeUrl) {
sourceImg.src = newImgUrl;
largeImg.src = newLargeUrl;
largeImg.onload = function() {
ratio = largeImg.width / sourceImg.width;
};
}
class ImageMagnifier {
constructor(options) {
this.container = document.querySelector(options.container);
this.sourceImg = this.container.querySelector(options.sourceImg);
this.lens = this.container.querySelector(options.lens);
this.result = this.container.querySelector(options.result);
this.largeImgUrl = options.largeImgUrl;
this.init();
}
init() {
this.ratio = 2; // 默认比例
this.setupEvents();
this.preloadLargeImage();
}
preloadLargeImage() {
const img = new Image();
img.src = this.largeImgUrl;
img.onload = () => {
this.ratio = img.width / this.sourceImg.width;
};
}
setupEvents() {
this.sourceImg.addEventListener('mouseenter', this.handleEnter.bind(this));
this.sourceImg.addEventListener('mousemove', this.throttle(this.handleMove.bind(this), 16));
this.sourceImg.addEventListener('mouseleave', this.handleLeave.bind(this));
}
handleEnter() {
this.lens.style.display = 'block';
this.result.style.display = 'block';
}
handleMove(e) {
const rect = this.sourceImg.getBoundingClientRect();
let x = e.clientX - rect.left;
let y = e.clientY - rect.top;
// 边界检查
x = Math.max(this.lens.offsetWidth/2, Math.min(x, this.sourceImg.width - this.lens.offsetWidth/2));
y = Math.max(this.lens.offsetHeight/2, Math.min(y, this.sourceImg.height - this.lens.offsetHeight/2));
// 定位放大镜
this.lens.style.left = `${x - this.lens.offsetWidth/2}px`;
this.lens.style.top = `${y - this.lens.offsetHeight/2}px`;
// 计算放大位置
const bgX = (x - this.lens.offsetWidth/2) * this.ratio * -1;
const bgY = (y - this.lens.offsetHeight/2) * this.ratio * -1;
// 应用样式
this.result.style.backgroundImage = `url(${this.largeImgUrl})`;
this.result.style.backgroundSize = `${this.sourceImg.width * this.ratio}px ${this.sourceImg.height * this.ratio}px`;
this.result.style.backgroundPosition = `${bgX}px ${bgY}px`;
}
handleLeave() {
this.lens.style.display = 'none';
this.result.style.display = 'none';
}
throttle(fn, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall < delay) return;
lastCall = now;
return fn.apply(this, args);
};
}
}
// 使用示例
new ImageMagnifier({
container: '.magnifier-container',
sourceImg: '#sourceImg',
lens: '.magnifier-lens',
result: '.magnifier-result',
largeImgUrl: 'product-large.jpg'
});
图片闪烁问题:
will-change: transform
提升性能边界对齐不准:
// 添加补偿值
const offsetX = (sourceImg.width - sourceImg.naturalWidth) / 2;
const offsetY = (sourceImg.height - sourceImg.naturalHeight) / 2;
移动端双指缩放冲突:
sourceImg.addEventListener('touchstart', (e) => {
if (e.touches.length > 1) e.preventDefault();
}, { passive: false });
通过本文的讲解,我们实现了: 1. 原生JS图片放大镜核心功能 2. 完善的边界处理和性能优化 3. 响应式设计和移动端支持 4. 可复用的类封装实现
实际项目中可根据需求添加动画过渡、多图切换、不同放大模式(圆形/方形)等扩展功能。完整代码已包含关键注释,建议直接用于项目开发。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。