Use native JS for picture magnifier effect

The first step is to understand the mathematical algorithms:
Require mask width
Large Map, Large Map Display Area, Small Map, Mask Layer
1. Small maps are scaled to equal ratios
2. The mask layer is zoomed in and out of the map display area
Small/Large = Mask Layer/Large Map Display Area
Cover Layer = Large Map Display Area* (Small Map / Large Map);
    ------------------------------------------------
Large Map Active Area = Large Map-Large Map Display Area
Small Map Active Area = Small Map-Mask Layer

Cover Layer Offset/Small Map Active Area=Large Map Offset/Large Map Active Area

Large Map Offset = Large Map Active Area* (Mask Layer Offset / Small Map Active Area)
Large Map Offset = (Large Map-Large Map Display Area)* (Mask Layer Offset/(Small Map-Mask Layer))

  • Magnifier== 100*100 Orange Square For short: Square 1

  • Left Window== 200*200 Blue Square For short: Square 2

  • Right Window== 200*200 Purple Square For short: Square 3

  • Original == 400*400 Cyan Square for short: Square 4

In one expression, the left value of block 1 (or top value)/the left value of block 4 (or top value)=(-1)*the width of block 2/the width of block 4.What we need to note here is that the positioning parent of block 1 is block 2 and block 4 is block 3.In addition, the width of the small image is the same as that of the left window.The magnifier effect can be achieved by modifying the top and left values of block 4 equally proportionally according to the top and left values of block 1, and the box beyond is not visible.
 

Decomposition action:
1. Layout
2. Calculate the cover layer width and height
3. Move in and out event handling for small bindings
4. Bind the mouse to small for event handling
4.1. Calculate mask offset
            (e.clientX-zoom.offsetLeft-zoom.clientLeft-mask.offsetWidth/2)
4.2, specify maximum and minimum offsets for mask s
4.3. Calculate large map offset (reference formula)

 

Matters needing attention:
1. Mouse-in and mouse-move events should be added to small
2. The offsetX/offsetY value is not accurate and should be replaced by clientX/clientY

 

Design sketch:

 

Source code:

<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<title>Document</title>
		<style>
			/*Only small display areas can be placed in the entire div, and large display areas can be hidden, so that zoom attributes can be set directly*/
			
			.zoom {
				width: 200px;
				height: 200px;
				margin-left: 100px;
				margin-top: 100px;
				/*margin-top: 1000px;  Test reaction with scrollbars*/
				position: relative;
				border: solid 1px #000;
			}
			
			.big_area {
				/*Width and height of large display area can be changed directly*/
				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*/
			
			.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>
			// Get the corresponding node element
			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');

			// Set mask layer width, height, small map width divided by large map width multiplied by large display area border
			mask.style.width = (simg.offsetWidth / bimg.offsetWidth) * big.clientWidth + "px";
			mask.style.height = (simg.offsetHeight / bimg.offsetHeight) * big.clientHeight + "px";

			// Define the maximum margin of the mask layer, which is the maximum moving distance
			var maxW = simg.clientWidth - mask.offsetWidth;
			var maxH = simg.clientHeight - mask.offsetHeight;

			// Events occur when the mouse moves into a small display area: 1. Mask layer display 2. Large display area display
			small.onmouseenter = function() {
				mask.style.left = 0;
				big.style.left = 210 + "px";
			}
			// Incidents occur when the mouse moves into a small display area: 1. Mask layer disappears 2. Large display area disappears
			small.onmouseleave = function() {
				mask.style.left = -10000 + "px";
				big.style.left = -10000 + "px";
			}
			// Mouse moves in small display area
			small.onmousemove = function(e) {
				// Solve compatibility issues
				e = e || window.event;
				// Define two variables so that the mouse position is always in the middle of the mask position
				var nLeft = e.pageX - zoom.offsetLeft - zoom.clientLeft - mask.offsetWidth / 2;
				var nTop = e.pageY - zoom.offsetTop - zoom.clientTop - mask.offsetHeight / 2;

				// Setting the mask layer to always appear inside the small display area is to judge nLeft, nTop values
				nLeft = Math.min(maxW, Math.max(0, nLeft));
				nTop = Math.min(maxH, Math.max(0, nTop));

				// Cover Layer Position
				mask.style.left = nLeft + "px";
				mask.style.top = nTop + "px";

				// Set the position of the large picture to follow the percentage shift of the mask layer (grammar brought in)
				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>

There is also a jqzoom plugin for magnifying effect:

Links: https://pan.baidu.com/s/1FwUEYyzhqnO31-uZqtSPPw 
Extraction Code: t7yf
 

 

 

 

 

 

 


 

Keywords: Front-end

Added by whisher06 on Tue, 10 Sep 2019 06:14:56 +0300