效果如下:

代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品图片切换展示 - 极客定制</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 40px 20px;
}
.product-gallery {
display: flex;
gap: 20px;
background: #fff;
padding: 30px;
border-radius: 16px;
box-shadow: 0 10px 40px rgba(0,0,0,0.08);
max-width: 900px;
width: 100%;
position: relative;
}
/* 左侧缩略图列表 */
.thumbnail-list {
display: flex;
flex-direction: column;
gap: 12px;
width: 80px;
flex-shrink: 0;
max-height: 500px;
overflow-y: auto;
overflow-x: hidden;
padding-right: 4px;
}
.thumbnail-list::-webkit-scrollbar {
width: 4px;
}
.thumbnail-list::-webkit-scrollbar-track {
background: transparent;
}
.thumbnail-list::-webkit-scrollbar-thumb {
background: #ddd;
border-radius: 4px;
}
.thumbnail-list::-webkit-scrollbar-thumb:hover {
background: #bbb;
}
.thumbnail-list {
scrollbar-width: thin;
scrollbar-color: #ddd transparent;
}
.thumb-item {
width: 76px;
height: 76px;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
border: 2px solid transparent;
transition: all 0.3s ease;
position: relative;
background: #f8f8f8;
flex-shrink: 0;
}
.thumb-item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.thumb-item:hover img {
transform: scale(1.05);
}
.thumb-item.active {
border-color: #ff6b35;
box-shadow: 0 0 0 3px rgba(255, 107, 53, 0.15);
}
.thumb-item.active::after {
content: '';
position: absolute;
inset: 0;
border-radius: 6px;
border: 2px solid #ff6b35;
pointer-events: none;
}
/* 右侧大图区域 */
.main-image-wrapper {
flex: 1;
position: relative;
border-radius: 12px;
min-height: 500px;
display: flex;
align-items: center;
justify-content: center;
}
.main-image-container {
position: relative;
width: 100%;
height: 100%;
min-height: 500px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
cursor: crosshair;
border-radius: 12px;
background: #f8f8f8;
}
.main-image-container img {
max-width: 100%;
max-height: 500px;
object-fit: contain;
transition: opacity 0.3s ease, transform 0.3s ease;
opacity: 1;
}
.main-image-container img.fade-out {
opacity: 0;
transform: scale(0.98);
}
/* 放大镜 — 正方形 */
.zoom-lens {
position: absolute;
width: 140px;
height: 140px;
border: 2px solid rgba(255, 107, 53, 0.9);
background: rgba(255, 255, 255, 0.15);
pointer-events: none;
opacity: 0;
transition: opacity 0.2s ease;
box-shadow: 0 0 15px rgba(0,0,0,0.15), inset 0 0 20px rgba(255,255,255,0.3);
display: none;
z-index: 20;
left: 0;
top: 0;
}
/* 放大结果窗口 — 正方形 */
.zoom-result {
position: absolute;
top: 30px;
left: calc(100% + 20px);
width: 400px;
height: 400px;
border-radius: 12px;
overflow: hidden;
border: 1px solid #eee;
background: #fff;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
box-shadow: 0 10px 40px rgba(0,0,0,0.15);
z-index: 100;
}
.zoom-result.visible {
opacity: 1;
}
.zoom-result img {
position: absolute;
top: 0;
left: 0;
object-fit: cover;
transition: none;
}
/* 图片指示器 */
.image-indicator {
position: absolute;
bottom: 15px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 6px;
z-index: 10;
}
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(0,0,0,0.2);
transition: all 0.3s ease;
cursor: pointer;
}
.dot.active {
background: #ff6b35;
width: 20px;
border-radius: 4px;
}
/* 提示文字 */
.zoom-hint {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
background: rgba(0,0,0,0.6);
color: #fff;
padding: 6px 14px;
border-radius: 20px;
font-size: 12px;
pointer-events: none;
opacity: 0.8;
transition: opacity 0.3s ease;
z-index: 15;
}
.main-image-container:hover .zoom-hint {
opacity: 0;
}
/* 响应式 */
@media (max-width: 768px) {
.product-gallery {
flex-direction: column-reverse;
align-items: center;
}
.thumbnail-list {
flex-direction: row;
width: 100%;
max-height: none;
overflow-x: auto;
overflow-y: hidden;
padding-right: 0;
padding-bottom: 4px;
justify-content: flex-start;
}
.thumbnail-list::-webkit-scrollbar {
height: 4px;
}
.thumb-item {
width: 76px;
height: 76px;
}
.main-image-wrapper {
min-height: 350px;
}
.main-image-container {
min-height: 350px;
}
.zoom-result {
display: none !important;
}
.zoom-lens {
display: none !important;
}
}
</style>
<base target="_blank">
</head>
<body>
<div class="product-gallery" id="productGallery">
<!-- 左侧缩略图 — 只需在这里写图片 -->
<div class="thumbnail-list" id="thumbnailList">
<div class="thumb-item active" data-main="https://images.unsplash.com/photo-1521572163474-6864f6400bc2?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1521572163474-6864f6400bc2?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1521572163474-6864f6400bc2?w=200&h=200&fit=crop" alt="商品图1">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1581655353564-dfba12320e24?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1581655353564-dfba12320e24?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1581655353564-dfba12320e24?w=200&h=200&fit=crop" alt="商品图2">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1576566588028-4147f3842f27?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1576566588028-4147f3842f27?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1576566588028-4147f3842f27?w=200&h=200&fit=crop" alt="商品图3">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1618354691373-d851c5c3a990?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1618354691373-d851c5c3a990?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1618354691373-d851c5c3a990?w=200&h=200&fit=crop" alt="商品图4">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1503341504253-dff4815485f1?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1503341504253-dff4815485f1?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1503341504253-dff4815485f1?w=200&h=200&fit=crop" alt="商品图5">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1562157873-818bc0726f68?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1562157873-818bc0726f68?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1562157873-818bc0726f68?w=200&h=200&fit=crop" alt="商品图6">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1556821840-3a63f95609a7?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1556821840-3a63f95609a7?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1556821840-3a63f95609a7?w=200&h=200&fit=crop" alt="商品图7">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1583743814966-8936f5b7be1a?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1583743814966-8936f5b7be1a?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1583743814966-8936f5b7be1a?w=200&h=200&fit=crop" alt="商品图8">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1596755094514-f87e34085b2c?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1596755094514-f87e34085b2c?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1596755094514-f87e34085b2c?w=200&h=200&fit=crop" alt="商品图9">
</div>
<div class="thumb-item" data-main="https://images.unsplash.com/photo-1620799140408-edc6dcb6d633?w=800&h=800&fit=crop" data-zoom="https://images.unsplash.com/photo-1620799140408-edc6dcb6d633?w=1600&h=1600&fit=crop">
<img src="https://images.unsplash.com/photo-1620799140408-edc6dcb6d633?w=200&h=200&fit=crop" alt="商品图10">
</div>
</div>
<!-- 右侧大图 -->
<div class="main-image-wrapper" id="mainImageWrapper">
<div class="main-image-container" id="mainImageContainer">
<img id="mainImage" src="" alt="主图">
<div class="zoom-lens" id="zoomLens"></div>
<div class="zoom-hint">鼠标悬停查看放大效果</div>
</div>
<div class="image-indicator" id="imageIndicator"></div>
</div>
<!-- 放大窗口 — 正方形 -->
<div class="zoom-result" id="zoomResult">
<img id="zoomResultImg" src="" alt="放大图">
</div>
</div>
<script>
let currentIndex = 0;
let isZoomVisible = false;
let zoomReady = false;
const mainImage = document.getElementById('mainImage');
const zoomResultImg = document.getElementById('zoomResultImg');
const mainContainer = document.getElementById('mainImageContainer');
const zoomLens = document.getElementById('zoomLens');
const zoomResult = document.getElementById('zoomResult');
const mainWrapper = document.getElementById('mainImageWrapper');
const productGallery = document.getElementById('productGallery');
const thumbnailList = document.getElementById('thumbnailList');
const imageIndicator = document.getElementById('imageIndicator');
const thumbItems = () => thumbnailList.querySelectorAll('.thumb-item');
function getImagesFromDOM() {
const items = thumbItems();
return Array.from(items).map(item => ({
thumb: item.querySelector('img').src,
main: item.dataset.main,
zoom: item.dataset.zoom
}));
}
function renderDots(count) {
imageIndicator.innerHTML = '';
for (let i = 0; i < count; i++) {
const dot = document.createElement('div');
dot.className = 'dot' + (i === 0 ? ' active' : '');
dot.addEventListener('click', () => switchImage(i));
imageIndicator.appendChild(dot);
}
}
function switchImage(index) {
const items = thumbItems();
const images = getImagesFromDOM();
if (index === currentIndex) return;
if (index < 0 || index >= images.length) return;
currentIndex = index;
zoomReady = false;
items.forEach((item, i) => {
item.classList.toggle('active', i === index);
});
const dots = imageIndicator.querySelectorAll('.dot');
dots.forEach((dot, i) => {
dot.classList.toggle('active', i === index);
});
mainImage.classList.add('fade-out');
setTimeout(() => {
mainImage.src = images[index].main;
zoomResultImg.src = images[index].zoom;
mainImage.classList.remove('fade-out');
waitForImagesReady();
}, 200);
const activeItem = items[index];
if (activeItem) {
activeItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
function bindThumbnailEvents() {
const items = thumbItems();
items.forEach((item, index) => {
item.addEventListener('mouseenter', () => switchImage(index));
item.addEventListener('click', () => switchImage(index));
});
}
function positionZoomResult() {
if (window.innerWidth <= 768) return;
const wrapperRect = mainWrapper.getBoundingClientRect();
const galleryRect = productGallery.getBoundingClientRect();
zoomResult.style.top = (wrapperRect.top - galleryRect.top) + 'px';
zoomResult.style.left = (wrapperRect.right - galleryRect.left + 20) + 'px';
}
// 等待主图和放大图都加载完成
function waitForImagesReady() {
let mainLoaded = false;
let zoomLoaded = false;
function check() {
if (mainLoaded && zoomLoaded) {
initZoomLens();
zoomReady = true;
return;
}
setTimeout(check, 50);
}
function onMainLoad() {
mainLoaded = true;
mainImage.removeEventListener('load', onMainLoad);
}
function onZoomLoad() {
zoomLoaded = true;
zoomResultImg.removeEventListener('load', onZoomLoad);
}
if (mainImage.complete && mainImage.naturalWidth > 0) {
mainLoaded = true;
} else {
mainImage.addEventListener('load', onMainLoad);
}
if (zoomResultImg.complete && zoomResultImg.naturalWidth > 0) {
zoomLoaded = true;
} else {
zoomResultImg.addEventListener('load', onZoomLoad);
}
check();
}
// 初始化放大镜
function initZoomLens() {
if (!mainImage.naturalWidth || !zoomResultImg.naturalWidth) return;
zoomResultImg.style.width = zoomResultImg.naturalWidth + 'px';
zoomResultImg.style.height = zoomResultImg.naturalHeight + 'px';
}
// 检测鼠标是否在当前图片的实际显示区域内
function isMouseInImage(e) {
const imgRect = mainImage.getBoundingClientRect();
return (
e.clientX >= imgRect.left &&
e.clientX <= imgRect.right &&
e.clientY >= imgRect.top &&
e.clientY <= imgRect.bottom
);
}
// 显示放大镜和放大窗口
function showZoom() {
if (isZoomVisible) return;
isZoomVisible = true;
positionZoomResult();
zoomLens.style.display = 'block';
zoomResult.classList.add('visible');
requestAnimationFrame(() => {
zoomLens.style.opacity = '1';
});
}
// 隐藏放大镜和放大窗口
function hideZoom() {
if (!isZoomVisible) return;
isZoomVisible = false;
zoomLens.style.opacity = '0';
zoomResult.classList.remove('visible');
setTimeout(() => {
if (!isZoomVisible) zoomLens.style.display = 'none';
}, 200);
}
// 更新放大镜位置
function updateZoomPosition(e) {
if (!zoomReady) return;
const imgRect = mainImage.getBoundingClientRect();
const containerRect = mainContainer.getBoundingClientRect();
// 图片在容器中的 CSS 显示区域
const imgLeft = imgRect.left - containerRect.left;
const imgTop = imgRect.top - containerRect.top;
const imgDisplayW = imgRect.width;
const imgDisplayH = imgRect.height;
// 放大镜尺寸固定(从 CSS 读取)
const lensSize = 140;
// 鼠标在容器中的位置
const mouseX = e.clientX - containerRect.left;
const mouseY = e.clientY - containerRect.top;
// 放大镜左上角位置:以鼠标为中心,但整个放大镜不能超出图片 CSS 边界
let lensLeft = mouseX - lensSize / 2;
let lensTop = mouseY - lensSize / 2;
// 限制放大镜在图片边界内(当鼠标到边缘,放大镜被"顶住")
lensLeft = Math.max(imgLeft, Math.min(lensLeft, imgLeft + imgDisplayW - lensSize));
lensTop = Math.max(imgTop, Math.min(lensTop, imgTop + imgDisplayH - lensSize));
zoomLens.style.left = lensLeft + 'px';
zoomLens.style.top = lensTop + 'px';
// 放大镜在图片 CSS 显示区域内的相对比例(0~1)
const ratioX = (lensLeft - imgLeft) / (imgDisplayW - lensSize);
const ratioY = (lensTop - imgTop) / (imgDisplayH - lensSize);
// 放大图偏移:按同样的比例映射到放大图 natural 尺寸
const resultX = -ratioX * (zoomResultImg.naturalWidth - zoomResult.offsetWidth);
const resultY = -ratioY * (zoomResultImg.naturalHeight - zoomResult.offsetHeight);
zoomResultImg.style.left = resultX + 'px';
zoomResultImg.style.top = resultY + 'px';
}
// 鼠标进入容器
mainContainer.addEventListener('mouseenter', function(e) {
if (window.innerWidth <= 768) return;
if (!zoomReady) return;
if (isMouseInImage(e)) {
showZoom();
updateZoomPosition(e);
}
});
// 鼠标在容器内移动
mainContainer.addEventListener('mousemove', function(e) {
if (window.innerWidth <= 768) return;
if (!zoomReady) return;
if (isMouseInImage(e)) {
showZoom();
updateZoomPosition(e);
} else {
hideZoom();
}
});
// 鼠标离开容器
mainContainer.addEventListener('mouseleave', function() {
hideZoom();
});
window.addEventListener('resize', function() {
positionZoomResult();
initZoomLens();
});
document.addEventListener('keydown', function(e) {
const total = thumbItems().length;
if (e.key === 'ArrowLeft' && currentIndex > 0) {
switchImage(currentIndex - 1);
} else if (e.key === 'ArrowRight' && currentIndex < total - 1) {
switchImage(currentIndex + 1);
}
});
function init() {
const images = getImagesFromDOM();
if (images.length === 0) return;
renderDots(images.length);
bindThumbnailEvents();
mainImage.src = images[0].main;
zoomResultImg.src = images[0].zoom;
waitForImagesReady();
}
init();
</script>
</body>
</html>



aipay无法跳转充值,咋整呢
用了几天,发现不分联通电信,在傍晚高峰期都会变得很慢。总体能用,这么便宜还要什么自行车
另外联通测速很好 10M+,电信下载只有100k,上传倒是很快