```javascript
//使用:
1、引用
import Magnifier from '@/components/Magnifier/index.vue'
2、使用 (传递参数为 imageList :图片列表)
<Magnifier class="myMagnifier" :imageList="list"></Magnifier>
<script setup>
//导入鼠标位置控制插件
import { useMouseInElement } from '@vueuse/core'
import {ref,watch} from 'vue'
const props=defineProps({
imageList: {
type: Array,
},
});
//定义当前index
const activeIndex=ref(0)
//小图片位置:
const smallPosi=ref(0)
//点击图片切换index
const changeIndex=(i)=>{
activeIndex.value=i
//更改小图片位置:
if(activeIndex.value>=props.imageList.length-4){
smallPosi.value=-100*(props.imageList.length-4)
}else{
smallPosi.value=-100*activeIndex.value
}
}
//引用
const target = ref(null)
//获取鼠标相对位置(X,Y)和是否离开目标区域
const { elementX, elementY, isOutside } = useMouseInElement(target)
//控制鼠标跟随图片移动,(鼠标移动,mask的位置发生变化)
//mask位置
const left=ref(0)
const top= ref(0)
//放大镜中图片显示位置:
const positionX = ref(0)
const positionY = ref(0)
//当鼠标位置elementX, elementY, isOutside发生改变时:
watch([ elementX, elementY, isOutside ],()=>{
// 如果鼠标没有移入到盒子里面 直接不执行后面的逻辑
if(isOutside.value) return
//鼠标进入到盒子中,开始执行计算:
if(elementX.value>100&&elementX.value<300){
left.value=elementX.value-100
}
if(elementY.value>100&&elementY.value<300){
top.value=elementY.value-100
}
// 处理边界
if (elementX.value > 300) { left.value = 200 }
if (elementX.value < 100) { left.value = 0 }
if (elementY.value > 300) { top.value = 200 }
if (elementY.value < 100) { top.value = 0 }
// 控制大图的显示位置
positionX.value = -left.value * 2
positionY.value = -top.value * 2
})
//点击按钮切换小图片位置:
const upView=()=>{
if( smallPosi.value>=0){
return
}
smallPosi.value=smallPosi.value+100
}
const dowmView=()=>{
if(smallPosi.value<=-100*(props.imageList.length-4)){
return
}
smallPosi.value=smallPosi.value-100
}
</script>
<template>
<div class="goods-image">
<!-- 左侧-->
<div class="left">
<div class="main" ref="target">
<img :src="imageList[activeIndex]" alt="" />
<!-- 蒙层小滑块 -->
<div class="mask" :style="{ left: `${left}px`, top: `${top}px` }"></div>
</div>
<!-- 小图列表 -->
<div class="small" >
<span class="up" @click="upView"><el-icon><ArrowUp /></el-icon></span>
<ul :style="{ top: `${smallPosi}px`,transition:`0.5s` }">
<li v-for="(img, i) in imageList" :key="i" @click="changeIndex(i)" :class="{active:i===activeIndex}">
<img :src="img" alt="" />
</li>
</ul>
<span class="down" @click="dowmView"><el-icon><ArrowDown /></el-icon></span>
</div>
</div>
<!-- 右侧 放大镜 -->
<div class="right" :style="[
{
backgroundImage: `url(${imageList[activeIndex]})`,
backgroundPositionX: `${positionX}px`,
backgroundPositionY: `${positionY}px`,
},
]" v-show="!isOutside">
</div>
</div>
</template>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.goods-image{
position: relative;
.left{
width: 510px;
height: 400px;
display: flex;
.main{
width: 400px;
height: 400px;
position: relative;
img{
width: 400px;
height: 400px;
}
.mask{
width: 200px;
height: 200px;
position:absolute;
z-index: 1;
background: rgba(0, 0, 0, 0.2);
left: 0;
top: 0;
}
}
.small{
position: relative;
width: 100px;
height: 400px;
margin-left: 10px;
overflow: hidden;
.up,.down{
text-align: center;
height: 10px;
width: 30px;
margin-top: 0px;
border: 1px solid darkmagenta;
background-color: darkkhaki;
font-size: 10px;
z-index: 2;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.up{
top: 0;
}
.down{
bottom: 0;
}
ul{
width: 100px;
position: absolute;
height: 400px;
li{
width: 100px;
height: 100px;
img{
width: 100%;
height: 100%;
}
}
}
}
}
.right{
width: 400px;
height: 400px;
background-color: pink;
position: absolute;
top: 0;
left: 520px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
z-index: 99;
}
}
.active {
border: 2px solid darkorange;
}
</style>