图片放大镜常规原理解析和实现(转)

1,052 阅读3分钟

一、原因


其实就是当初的学习。想想前端一年半,还不会图片放大很羞愧啊。



二、原理解析



1、html结构编写


<div
  ref="zoom"
  class="main-img"
  @mouseenter="mouseenter"
  @mouseleave="mouseleave"
>
  <img src="../../assets/img/icon/dogHead.jpg" alt="" />
  <div
    ref="mask"
    class="mask"
    :style="{ top: mask.top + 'px', left: mask.left + 'px' }"
  ></div>
</div>
<div class="preview">
  <img src="../../assets/img/icon/dogHead.jpg" alt="" />
</div>


结构非常简单,没什么难度。



2、小图进入定位


这里比较麻烦,我贴一篇文章,供大家理解一些参数。

鼠标事件以及clientX、offsetX、screenX、pageX、x的区别

然后关键的进入位移计算方式是如下

(e.clientX-zoom.offsetLeft-zoom.clientLeft-mask.offsetWidth/2)


注意事件要用mouseenter,这个事件不会重复调用,不会冒泡。


我的代码:


	const mask = this.$refs["mask"];
const zoom = this.$refs["zoom"];
const endY = zoom.offsetHeight - mask.offsetHeight;
const endX = zoom.offsetWidth - mask.offsetWidth;
const Y =
  e.clientY - zoom.offsetTop - zoom.clientTop - mask.offsetHeight / 2;
const X =
  e.clientX - zoom.offsetLeft - zoom.clientLeft - mask.offsetWidth / 2;
this.mask = {
  top: Y > endY ? endY : Y < 0 ? 0 : Y,
  left: X > endX ? endX : X < 0 ? 0 : X
};


这就是当鼠标进入的时候所需要进行的操作。主要是计算当前位置,和进行最大最小的设置。



3、让小图的div动起来。


这个看我上篇文章:

指令模式让div移动起来

掘金地址:https://juejin.cn/post/6844904016900538382

里面讲述了基本的移动原理



4、图片放大

这个实际上懂得人知道后发现真的简单。实际上就是一个是消费者正常看的图,还有一个是你需要放大得img,这个img你给设置宽高是原图的对应倍数,就实现放大效果了。



5、移动的时候图片对应移动。预览


这个就更加简单了,只要你计算出图片翻倍的大小,然后移动距离乘以倍数就是你预览的图的位置。




三、实际代码


这里我就当一次盗版了,因为本次博客的主要目的是学习原理。并且我已经懂了。所以这里放另一位大神的代码了

原文地址:https://blog.csdn.net/a5252145/article/details/82191370


<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style>
		/*整个div中只放置小显示区域即可,大显示区域隐藏,这样直接对zoom设置属性就行了*/
		.zoom{
			width: 200px;
			height: 200px;
			margin-left: 100px;
			margin-top: 100px;
			/*margin-top: 1000px;  测试有滚动条情况下反应*/
			position: relative;
			border: solid 1px #000;
		}
		.big_area{
			/*大显示区域宽高可直接改变*/
			width: 200px;
			height: 200px;
			position: absolute;
			left: -10000px;
			top: -1px;
			border: solid 1px #000;
			overflow: hidden;
		}
		.big_area img{
			position: absolute;
			left: 0;
			top: 0;
		}
		/*遮罩层*/
		.mask{
			position: absolute;
			left: -10000px;
			top: 0;
			width: 100px;
			height: 100px;
			background: #000;
			opacity:0.65;
			filter:alpha(opacity=65);
		}
	</style>
</head>
<body>
	<div class="zoom">
		<div class="small_area">
			<img src="images/zoom.jpg" width="200" height="200" />
			<span class="mask"></span>
		</div>
		<div class="big_area">
			<img src="images/zoom.jpg" width="620" height="620">
		</div>
	</div>
 
	<script>
		
		// 获取相应节点元素
		var zoom = document.querySelector('.zoom');
		var simg = document.querySelector('.small_area img');
		var bimg = document.querySelector('.big_area img');
		var big = document.querySelector('.big_area');
		var small = document.querySelector('.small_area');
		var mask = document.querySelector('.mask');
 
		// 设置遮罩层宽高  小图宽 除以 大图宽 乘以 大显示区域边框
		mask.style.width = (simg.offsetWidth/bimg.offsetWidth)*big.clientWidth+"px";
		mask.style.height = (simg.offsetHeight/bimg.offsetHeight)*big.clientHeight+"px";
 
		// 定义遮罩层最大边距,也就是最大移动距离
		var maxW = simg.clientWidth - mask.offsetWidth;
		var maxH = simg.clientHeight - mask.offsetHeight;
 
		// 鼠标移入小显示区域发生事件:1.遮罩层显示 2.大显示区域显示
		small.onmouseenter=function(){
			mask.style.left = 0;
			big.style.left = 210+"px";
		}
		// 鼠标移入小显示区域发生事件:1.遮罩层消失 2.大显示区域消失
		small.onmouseleave=function(){
			mask.style.left = -10000+"px";
			big.style.left = -10000+"px";
		}
		// 鼠标在小显示区域移动
		small.onmousemove=function(e){
			// 解决兼容问题
			e = e || window.event;
			// 定义两个变量 让鼠标位置一直处于遮罩层位置中间
			var nLeft = e.pageX-zoom.offsetLeft-zoom.clientLeft-mask.offsetWidth/2;
			var nTop = e.pageY-zoom.offsetTop-zoom.clientTop-mask.offsetHeight/2;
 
			// 设置遮罩层永远显示在小显示区域内部 也就是判断nLeft、nTop值
			nLeft = Math.min(maxW,Math.max(0,nLeft));
			nTop = Math.min(maxH,Math.max(0,nTop));
 
			// 遮罩层位置
			mask.style.left = nLeft+"px";
			mask.style.top = nTop+"px";
 
			// 设置大图片移动位置 跟随遮罩层百分比移动(语法带入)
			bimg.style.left = -(bimg.offsetWidth-big.clientWidth)*(nLeft/(simg.clientWidth-mask.offsetWidth))+"px";		
			bimg.style.top = -(bimg.offsetHeight-big.clientHeight)*(nTop/(simg.clientHeight-mask.offsetHeight))+"px";			
 
 
		}
	</script>
 
</body>
</html>