在電商網站中,商品圖片對使用者購買決策有著重要影響,尤其是在細節展示方面,圖片放大效果是一個很棒的功能。今天我們就來聊聊如何實現滑鼠懸停在商品圖片上時的區域性放大效果,類似天貓商品詳情頁中的互動形式。別擔心,這個功能其實並不複雜,只需要110行程式碼便可輕鬆實現。
一、需求分析
在天貓等電商平臺的商品詳情頁,當用戶將滑鼠懸停在商品圖片上時,會出現一個放大鏡效果。具體行為如下:
左邊是原始的商品圖片,當用戶將滑鼠移入圖片區域時,出現一個放大鏡樣式的遮罩層。
右邊是放大後的商品圖片,遮罩層移動時,右側的大圖片同步顯示遮罩層內的商品細節部分。
我們將基於這個需求實現一種簡單的區域性放大效果,透過 CSS 和 JavaScript 來控制圖片的同步移動。
二、實現思路
爲了更好地控制圖片的放大效果,我們採用以下實現方式:
兩張圖片: 一張小圖片放在左邊顯示,當滑鼠懸停時,會顯示一個遮罩層;右邊放置一張對應的大圖片,顯示小圖片區域性放大的區域。
遮罩層的移動: 透過監聽滑鼠在小圖片上的移動位置,動態計算遮罩層的座標,並將遮罩層在小圖片上的位置同步到大圖片上。
放大效果: 大圖片的背景位置會隨著遮罩層在小圖片上的移動實時調整,從而展現出區域性放大效果。
三、程式碼實現
1、HTML 結構
首先,我們需要設定好頁面的基本結構。我們用兩個盒子來展示圖片:左邊是放小圖片的盒子,右邊是放大圖片的盒子。遮罩層會放在小圖片上,當滑鼠移動時,右邊的大圖片就會顯示出對應的放大細節。
<div class="image-container"> <img id="small-image" class="small-image" src="https://picsum.photos/id/7/600/400.jpg" alt="小圖片"> <div class="zoom-lens" id="zoom-lens"></div> </div> <div class="zoom-result" id="zoom-result"></div>
主要由兩個部分組成,左側的小圖片image-container
和右側的大圖片展示區zoom-result
。遮罩層zoom-lens
在小圖片上移動時,大圖片背景同步更新。
2、CSS 樣式
在這一步,我們要透過 CSS 來設定圖片的樣式以及遮罩層的效果。image-container
用於限制小圖片的尺寸,zoom-lens
作為遮罩層,zoom-result
顯示大圖背景並控制其大小。
/* 小圖片盒子 */ .image-container { position: relative; width: 300px; /* 小圖片的寬度 */ height: 200px; /* 小圖片的高度 */ overflow: hidden; border: 1px solid #ddd; display: inline-block; margin-right: 20px; } /* 小圖片 */ .small-image { width: 100%; height: 100%; object-fit: cover; } /* 遮罩層 */ .zoom-lens { position: absolute; width: 100px; height: 100px; border: 1px solid #000; background-color: rgba(255, 255, 255, 0.4); pointer-events: none; /* 禁用遮罩層上的滑鼠事件 */ } /* 大圖片盒子 */ .zoom-result { width: 400px; /* 放大圖盒子的寬度 */ height: 300px; /* 放大圖盒子的高度 */ overflow: hidden; border: 1px solid #d4d4d4; position: absolute; left: 320px; top: 0; background-repeat: no-repeat; background-size: 1200px 800px; /* 背景圖大小與原圖大小成比例 */ }
在這裏,我們為小圖片和大圖片容器設定了尺寸,並透過 background-size
控制大圖片的放大倍數。遮罩層是半透明的矩形,會隨著滑鼠移動在小圖片上顯現。
3、JavaScript 實現邏輯
接下來,我們透過 JavaScript 監聽滑鼠移動,實現遮罩層與大圖片的同步移動效果。這一步是整個放大效果的核心。
實現邏輯:
監聽滑鼠在小圖片上的移動事件,獲取滑鼠相對於圖片的座標。
遮罩層根據滑鼠座標移動,防止其超出小圖片邊界。
根據遮罩層的位置,動態計算大圖片的背景顯示位置,從而呈現出區域性放大的效果。
const smallImage = document.getElementById('small-image'); const lens = document.getElementById('zoom-lens'); const result = document.getElementById('zoom-result'); // 設定大圖背景為原始大圖片 result.style.backgroundImage = `url('https://picsum.photos/id/7/1200/800.jpg')`; smallImage.addEventListener('mousemove', moveLens); smallImage.addEventListener('mouseenter', () => { lens.style.display = 'block'; result.style.display = 'block'; }); smallImage.addEventListener('mouseleave', () => { lens.style.display = 'none'; result.style.display = 'none'; }); function moveLens(e) { const { left, top, width, height } = smallImage.getBoundingClientRect(); const lensWidth = lens.offsetWidth; const lensHeight = lens.offsetHeight; // 計算滑鼠在圖片中的位置 let x = e.pageX - left; let y = e.pageY - top; // 防止遮罩層超出小圖片邊界 if (x < lensWidth / 2) x = lensWidth / 2; if (x > width - lensWidth / 2) x = width - lensWidth / 2; if (y < lensHeight / 2) y = lensHeight / 2; if (y > height - lensHeight / 2) y = height - lensHeight / 2; // 移動遮罩層 lens.style.left = `${x - lensWidth / 2}px`; lens.style.top = `${y - lensHeight / 2}px`; // 計算大圖片背景的位置,按比例移動 const bgX = ((x - lensWidth / 2) / width) * 1200; // 大圖寬度 1200 const bgY = ((y - lensHeight / 2) / height) * 800; // 大圖高度 800 // 設定大圖片的背景位置,確保大圖只移動遮罩層覆蓋區域 result.style.backgroundPosition = `-${bgX}px -${bgY}px`; }
上述便是放大效果的邏輯,效果圖如下:
4、 完整程式碼
最後再給出我們的完整程式碼。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>圖片放大效果</title> <style> /* 小圖片盒子 */ .image-container { position: relative; width: 300px; /* 小圖片的寬度 */ height: 200px; /* 小圖片的高度 */ overflow: hidden; border: 1px solid #ddd; display: inline-block; margin-right: 20px; } /* 小圖片 */ .small-image { width: 100%; height: 100%; object-fit: cover; } /* 遮罩層 */ .zoom-lens { position: absolute; width: 100px; height: 100px; border: 1px solid #000; background-color: rgba(255, 255, 255, 0.4); pointer-events: none; /* 禁用遮罩層上的滑鼠事件 */ } /* 大圖片盒子 */ .zoom-result { width: 400px; /* 放大圖盒子的寬度 */ height: 300px; /* 放大圖盒子的高度 */ overflow: hidden; border: 1px solid #d4d4d4; position: absolute; left: 320px; top: 0; background-repeat: no-repeat; background-size: 1200px 800px; /* 背景圖大小與原圖大小成比例 */ } </style> </head> <body> <div> <img id="small-image" src="https://picsum.photos/id/7/600/400.jpg" alt="小圖片" /> <div id="zoom-lens"></div> </div> <div id="zoom-result"></div> <script> const smallImage = document.getElementById('small-image'); const lens = document.getElementById('zoom-lens'); const result = document.getElementById('zoom-result'); // 設定大圖背景為原始大圖片 result.style.backgroundImage = `url('https://picsum.photos/id/7/1200/800.jpg')`; smallImage.addEventListener('mousemove', moveLens); smallImage.addEventListener('mouseenter', () => { lens.style.display = 'block'; result.style.display = 'block'; }); smallImage.addEventListener('mouseleave', () => { lens.style.display = 'none'; result.style.display = 'none'; }); function moveLens(e) { const { left, top, width, height } = smallImage.getBoundingClientRect(); const lensWidth = lens.offsetWidth; const lensHeight = lens.offsetHeight; // 計算滑鼠在圖片中的位置 let x = e.pageX - left; let y = e.pageY - top; // 防止遮罩層超出小圖片邊界 if (x < lensWidth / 2) x = lensWidth / 2; if (x > width - lensWidth / 2) x = width - lensWidth / 2; if (y < lensHeight / 2) y = lensHeight / 2; if (y > height - lensHeight / 2) y = height - lensHeight / 2; // 移動遮罩層 lens.style.left = `${x - lensWidth / 2}px`; lens.style.top = `${y - lensHeight / 2}px`; // 計算大圖片背景的位置,按比例移動 const bgX = ((x - lensWidth / 2) / width) * 1200; // 大圖寬度 1200 const bgY = ((y - lensHeight / 2) / height) * 800; // 大圖高度 800 // 設定大圖片的背景位置,確保大圖只移動遮罩層覆蓋區域 result.style.backgroundPosition = `-${bgX}px -${bgY}px`; } </script> </body> </html>