Bootstrap

Vue3---放大镜的实现

1. 通过小图切换大图实现:

思路:维护一个数组图片列表, 鼠标划入小图记录当前小图下标值,通过下标值
在数组中取对应图片 ,显示到大图位置
2. 放大镜效果实现------滑块跟随鼠标移动
useMouseInElement | VueUse
思路: 获取到当前的 鼠标在盒子内的相对位置 vueUse提供的 useMouseInElement ),
制滑块跟随鼠标移动(left/top)
1. 有效移动范围内的计算逻辑
横向:100 < elementX < 300, left = elementX - 小滑块宽度一半
纵向: 100 < elementY < 300, top = elementY - 小滑块高度一半
2. 边界距离控制
横向:elementX > 300 left = 200 elementX < 100 left = 0
纵向:elementY > 300 top = 200 elementY < 100 top = 0
3. 放大镜效果实现 - 大图效果实现
思路:大图的移动方向和滑块移动方向相反,且数值为2倍
4. 放大镜效果实现 - 鼠标移入控制显隐
思路:鼠标移入盒子(isOutside),滑块和大图才显示(v-show)
<script setup>
import {ref, watch} from "vue";
import {useMouseInElement} from '@vueuse/core'

// 图片列表
const imageList = [
    "https://yanxuan-item.nosdn.127.net/d917c92e663c5ed0bb577c7ded73e4ec.png",
    "https://yanxuan-item.nosdn.127.net/e801b9572f0b0c02a52952b01adab967.jpg",
    "https://yanxuan-item.nosdn.127.net/b52c447ad472d51adbdde1a83f550ac2.jpg",
    "https://yanxuan-item.nosdn.127.net/f93243224dc37674dfca5874fe089c60.jpg",
    "https://yanxuan-item.nosdn.127.net/f881cfe7de9a576aaeea6ee0d1d24823.jpg"
]

// 小图切换大图显示
const activeindex = ref(0)
const enterhandler = (i) => {
    activeindex.value = i
}

// 获取鼠标相对位置
const target = ref(null)
const {elementX, elementY, isOutside} = useMouseInElement(target)

// 控制滑块跟踪数百哦移动(监听elementX/Y变化,一旦变化,重新设置left/top)
const left = ref(0)
const top = ref(0)
const positionX = ref(0)
const positionY = ref(0)
watch([elementX, elementY], () => {
    console.log('xy变化了')
    
    //如果鼠标没有在盒子里面,直接不执行后面的逻辑
    if(isOutside.value) return
    // console.log('后续逻辑执行了')
    
    // 有效范围内控制滑块距离
    // 横向
    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

})
</script>


<template>
  {{ elementX }}-------{{ elementY }}-------{{ isOutside }}
    <div class="goods-image">
        <!-- 左侧大图-->
        <div class="middle" ref="target">
            <img :src="imageList[activeindex]" alt=""/>
            <!-- 蒙层小滑块 -->
            <div class="layer" v-show="!isOutside" :style="{ left: `${left}px`, top: `${top}px` }"></div>
        </div>
        <!-- 小图列表 -->
        <ul class="small">
            <li v-for="(img, i) in imageList" :key="i" @mouseenter="enterhandler(i)"
                :class="{ active:i === activeindex }">
                <img :src="img" alt=""/>
            </li>
        </ul>
        <!-- 放大镜大图 -->
        <div class="large" :style="[
      {
        backgroundImage: `url(${imageList[0]})`,
        backgroundPositionX: `${positionX}px`,
        backgroundPositionY: `${positionY}px`,
      },
   ]"  v-show="!isOutside" ></div>

    </div>
</template>

;