我们先看看效果图
废话不多说,直接上代码(注释都在代码中)
要求:你需要准备一个800*800的图片(下面代码使用的是网络图片,如果图片失效,请手动更换)
或者一个400*400的图片用来展示小图一个800*800的图片用来展示大图
下面的代码只是实现了静态样式,如果你需要实现更多功能请独自完成开发。
可以将获取元素的as类型断言的语句去掉,这样就可以在js的环境下运行
<template>
<div class="fangda">
<div class="contenr">
<!-- 存放大图,小图和遮罩层 -->
<div class="simg">
<img src="@/assets/styles/images/列表图片1.jpg" alt="">
<!-- 遮罩层 -->
<div class="box"></div>
</div>
<!-- 大图 -->
<div class="bimg">
<img class="p-img" src="@/assets/styles/images/列表图片1.jpg" alt="">
</div>
</div>
<!-- 右侧图片列表 -->
<div class="list">
<ul>
<li v-for="item in 5" :key="item"><img src="@/assets/styles/images/列表图片1.jpg" alt=""></li>
</ul>
</div>
</div>
</template>
<script setup lang='ts'>
import { onMounted } from 'vue'
onMounted(() => {
// 利用vue3的钩子函数,获取DOM元素
const { simg, box, bimg, pImg, list } = getElements()
// 获取元素
function getElements() {
// 如果你是js的项目可以把as 语句去掉
const simg = document.querySelector('.simg') as HTMLDivElement
const box = document.querySelector('.box') as HTMLDivElement
const bimg = document.querySelector('.bimg') as HTMLDivElement
const pImg = document.querySelector('.p-img') as HTMLImageElement
const list = document.querySelector('.list') as HTMLDivElement
return { simg, box, bimg, pImg, list }
}
// 当鼠标滑过左侧小图片的时候显示遮罩层和大盒子
const handleMouseOver = () => {
box.style.display = 'block'
bimg.style.display = 'block'
list.style.display = 'none'
}
// 鼠标离开左侧小图片的时候隐藏遮罩层和大盒子
const handleMouseLeave = () => {
box.style.display = 'none';
bimg.style.display = 'none';
list.style.display = 'block'
}
const handleMouseMove = (e: MouseEvent) => {
// 阴影的距离:鼠标的位置-盒子的位置-阴影宽高的一半
let X: number = e.clientX - simg.offsetLeft - box.offsetWidth / 2
let Y: number = e.clientY - bimg.offsetTop - box.offsetHeight / 2
// 让阴影移动
// 位置限定
const maxWidth = simg.offsetWidth - box.offsetWidth;
const maxHeight = simg.offsetHeight - box.offsetHeight;
X = Math.max(0, Math.min(X, maxWidth));
Y = Math.max(0, Math.min(Y, maxHeight));
// 让遮罩层动起来
box.style.left = X + 'px'
box.style.top = Y + 'px'
// 让大盒子中的的图片动起来
// 因为大盒子中图片和小盒子中图片比是2:1所以需要大盒子移动的唯一是小盒子的2倍,并且方向相反
pImg.style.left = -(2 * X) + 'px'
pImg.style.top = -(2 * Y) + 'px'
}
// 给小盒子绑定事件
simg.addEventListener('mouseover', handleMouseOver)
simg.addEventListener('mouseleave', handleMouseLeave)
simg.addEventListener('mousemove', handleMouseMove)
})
</script>
<style lang="less" scoped>
.fangda {
display: flex;
.contenr {
display: flex;
.simg {
width: 400px;
height: 400px;
position: relative;
img {
width: 100%;
height: 100%;
}
.box {
width: 200px;
height: 200px;
background-color: #333;
opacity: 0.1;
display: none;
position: absolute;
top: 0;
left: 0;
}
}
.bimg {
height: 400px;
width: 400px;
margin-left: 15px;
overflow: hidden;
display: none;
position: relative;
background-color: aqua;
// 让大图片位于最上方
z-index: 9999;
.p-img {
// 根据实际需要设置这两行代码
max-width: 800px;
max-height: 800px;
// 我的项目中受到全局样式影响,所以设置了上面的两行代码
position: absolute;
top: 0;
left: 0;
}
}
}
.list {
ul {
list-style: none;
width: 80px;
height: 400px;
padding: 0;
margin: 0;
li {
width: 64px;
height: 64px;
margin-bottom: 15px;
margin-left: 12px;
border-color: #27ba9b;
border: 2px solid transparent;
img {
width: 100%;
height: 100%;
vertical-align: middle;
}
}
}
}
}
</style>