效果展示和需求分析
效果展示
需求分析
- 在鼠标移入图片时出现放大镜范围框,展示内容框内容的大框在右边展示。
- 鼠标离开后,放大镜消失,大框也消失。
- 放大镜能随鼠标移动到想放大的区域。
代码分析
html 结构
<body>
<div class="photo-view">
<div class="small-picture">
<img src="upload/s3.png" alt="">
<div class="target-area"></div>
</div>
<div class="big-picture"><img src="upload/big.jpg" alt=""></div>
</div>
</body>
js 代码
var smallPicture = document.querySelector('.small-picture');
var bigPicture = document.querySelector('.big-picture');
var targetArea = smallPicture.children[1];
smallPicture.addEventListener('mouseover', function() {
targetArea.style.visibility = 'visible';
bigPicture.style.display = 'block';
document.addEventListener('mousemove', getDetail);
});
smallPicture.addEventListener('mouseout', function() {
targetArea.style.visibility = 'hidden';
bigPicture.style.display = 'none';
document.removeEventListener('mousemove', getDetail);
});
function getDetail(e) {
var x = e.pageX - smallPicture.offsetLeft; // 鼠标在小图片盒子x坐标
var y = e.pageY - smallPicture.offsetTop; // 鼠标在小图片盒子y坐标
var minX = targetArea.offsetWidth / 2;// 确定放大镜跟随鼠标移动的范围
var maxX = smallPicture.offsetWidth - minX;
var minY = targetArea.offsetHeight / 2;
var maxY = smallPicture.offsetHeight - minY;
if (x >= minX && x <= maxX) {
targetArea.style.left = -minX + x + 'px';
bigPicture.children[0].style.left = -(-minX + x) * 3 + 'px';
} else if (x < minX) {
targetArea.style.left = 0;
bigPicture.children[0].style.left = 0;
} else {
targetArea.style.left = -minX + maxX + 'px';
bigPicture.children[0].style.left = -(-minX + maxX) * 3 + 'px';
}
if (y >= minY && y <= maxY) {
targetArea.style.top = -minY + y + 'px';
bigPicture.children[0].style.top = -(-minY + y) * 3 + 'px';
} else if (y < minY) {
targetArea.style.top = 0;
bigPicture.children[0].style.top = 0;
} else {
targetArea.style.top = -minY + maxY + 'px';
bigPicture.children[0].style.top = -(-minY + maxY) * 3 + 'px';
}
}
可以将 if 判断语句下的代码改为:
function fnx() {
targetArea.style.left = -minX + x + 'px';
bigPicture.children[0].style.left = -(-minX + x) * 3 + 'px';
}
function fny() {
targetArea.style.top = -minY + y + 'px';
bigPicture.children[0].style.top = -(-minY + y) * 3 + 'px';
}
function fnx0() {
targetArea.style.left = 0;
bigPicture.children[0].style.left = 0;
}
function fnx1() {
targetArea.style.left = -minX + maxX + 'px';
bigPicture.children[0].style.left = -(-minX + maxX) * 3 + 'px';
}
function fny0() {
targetArea.style.top = 0;
bigPicture.children[0].style.top = 0;
}
function fny1() {
targetArea.style.top = -minY + maxY + 'px';
bigPicture.children[0].style.top = -(-minY + maxY) * 3 + 'px';
}
var flag = 0; // 如果在范围内移动即四个状态均不发生
if (x < minX) { flag = flag | 1; } // x 鼠标位置
if (x > maxX) { flag = flag | 2; }
if (y < minY) { flag = flag | 4; }
if (y > maxY) { flag = flag | 8; }
switch (flag) {
case 1: // 超出左边界(x < minX)
fnx0();
fny();
break;
case 2: // 超出右边界(x > maxX)
fnx1();
fny();
break;
case 4: // 超出上边界(x > maxX)
fny0();
fnx();
break;
case 5: // 同时超出左边界和上边界(x < minX && y < minY)
fnx0();
fny0();
break;
case 6: // 同时超出右边界和上边界(x > maxX && x > maxX)
fnx1();
fny0();
break;
case 8: // 超出下边界(y > minY)
fnx();
fny1();
break;
case 9: // 同时超出左边界和下边界(x < minX && y > minY)
fnx0();
fny1();
break;
case 10: // 同时超出右边界和下边界(x > maxX && y > minY)
fnx1();
fny1();
break;
default: // flag=0 范围内(x >= minX && x <= maxX && y >= minY && y <= maxY)
fnx();
fny();
break;
}
分析
1、先实现放大镜随鼠标移动,其实现原理与前面做过的模态框案例差不多,不过这里多了一个范围的控制。
2、鼠标位置在范围外面但在小图片盒子内也要设置放大镜的位置(else if 和 else 部分)否则会出现放大镜框无法与小图片的边缘重合的 bug 。
3、出现上述 bug 的原因是,理想情况下确实没必要设置那部分,因为超出那个范围后放大镜的(left、top)位置确实不用改变。但是在我们将鼠标移动到边界时是否能保证我们移到边界的那一像素到超出边界的一瞬间,鼠标移动事件能够被捕获(两边界能完全重合),而不是还没有鼠标就已经移出了边界导致不再改变放大镜位置,导致留缝隙,一像素值是非常小的,鼠标一动就不止了。
4、以上就是为什么要添加那一大串代码的原因。
5、实现大图移动的效果和一些计算原理:小图盒子大小200200(A)、放大区域盒子大小100100(B)、大图盒子大小300300(C)、大图片大小600600(D)。C / B = D / A = 3;即放大了三倍,所以在移动大图片时移动距离也是放大镜在小图片盒子的坐标的三倍。
6、只有自己亲手写过一遍才能真正直到会出现的问题和为什么要这么写。