<script setup>
// 交互实现思路:鼠标移入的时候记录一下当前的index值
import { ref, watch, reactive, onMounted } from 'vue'
import { useMouseInElement } from '@vueuse/core'
import axios from 'axios'
const imagesList = reactive(['/32bcffe3b6b897e2c97ff6edc9ceab97.jpeg','/5feef15bd62320b2aded98798e8f73c4.jpeg','/96399ac4eedfdc3cc0b331af71dc80ba.jpeg','/ea90dfd2998dac1b654215d608e104d7.jpg','/8834d7e78ce6f6eeec11b3b63d3a694f.jpeg']
)
const curIndex = ref(0);
const target = ref(null);
const isShow = ref(false);
// 左侧蒙层移动的位置
const left = ref(0);
const top = ref(0);
// 放大镜预览效果
const bgPosition = reactive({
backgroundPositionX:0 + 'px',
backgroundPositionY:0 + 'px'
});
const { elementX, elementY, isOutside } = useMouseInElement(target);
watch([elementX, elementY, isOutside] ,() =>{
/* 当鼠标移动不到一百的时候就说明,只移动蒙层自身的一半不到,因此实现放大镜的效果时会将此处蒙层所在位置,放大致2倍,也就是此图片的当前位置
当蒙层的大于100 而且小于300 这个时候蒙层的位置,则刚刚处于底图(原图)的中间(当然这个中间是指整个蒙层),在上下移动位置-100,是因为在样式中为其dom 设置 top left
是按照 dom 边来计算位置(所以刚好减去蒙层自身的一半,也就是蒙层的中间位置),因此 此时大于一百的蒙层位置被放大2倍之后background-positions 的位置才不会发生错乱
*/
if(elementX.value < 100) {
left.value = 0
}else if(100 < elementX.value && elementX.value < 300) {
left.value = elementX.value - 100
}else {
left.value = 200
}
// 垂直方向
if(elementY.value < 100) {
top.value = 0
}else if(100 < elementY.value && elementY.value < 300) {
top.value = elementY.value - 100
}else {
top.value = 200
}
bgPosition.backgroundPositionX = -elementX.value * 2 + "px"
bgPosition.backgroundPositionY = -elementY.value * 2 + "px"
isShow.value = isOutside.value
});
</script>
``````粗略图附上
``` 结构部分
<template>
<div class="goods-image">
<!-- 大图容器 -->
<div
class="large"
:style="[
{
backgroundImage: `url(${imagesList[curIndex]})`,
backgroundPositionX: bgPosition.backgroundPositionX ,
backgroundPositionY: bgPosition.backgroundPositionY ,
},
]"
v-if="!isShow"
></div>
<!-- 鼠标移动容器 -->
<div class="middle" ref="target">
<img :src="imagesList[curIndex]" alt="" />
<!-- 蒙层容器 -->
<!-- 添加动态style,让蒙层随着鼠标移动,挪动位置;Number类型,加上单位 -->
<div class="layer" :style="{
left: left+'px',
top: top+'px'
}" v-if="!isShow"></div>
</div>
<ul class="small">
<li
v-for="(img, i) in imagesList"
:key="i"
@mouseenter="curIndex=i"
:class="{active:curIndex===i}"
>
<img :src="img" alt="诸位可愿俯首" />
</li>
</ul>
</div>
</template>
<style scoped lang="less">
.goods-image {
width: 480px;
height: 400px;
position: relative;
display: flex;
.large {
position: absolute;
top: 0;
left: 412px;
width: 400px;
height: 400px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
background-repeat: no-repeat;
background-size: 800px 800px;
background-color: #f8f8f8;
}
.middle {
width: 400px;
height: 400px;
background: #f5f5f5;
// 蒙层容器
.layer {
width: 200px;
height: 200px;
background: rgba(0, 0, 0, 0.2);
left: 0;
top: 0;
cursor: pointer;
position: absolute;
}
img {
width: 100%;
height: 100%;
}
}
.small {
width: 80px;
li {
width: 68px;
height: 68px;
margin-left: 12px;
margin-bottom: 15px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
&:hover,
&.active {
border: 2px solid green;
}
}
}
}
</style>