1.调用useMouseElement函数,获取元素内鼠标移动的坐标。
// elementX , elementY target元素范围内的坐标值。
2.定义left,top变量蒙层移动的距离
left=elementX-蒙层盒子宽度的一半
top=element-蒙层盒子高度的一半
3.watch()监控elementX ,elementY。控制移动范围,
监听元素内鼠标移动的坐标变化=》控制蒙层移动=》计算蒙层:left和top的值
x轴
如 elementX<蒙层盒子宽度的一半,表示超出左边,让left=0
如elementX>盒子容器的宽度-蒙层盒子宽度的一半,表示超出右边,让left=盒子容器的宽度-蒙层盒子的宽度。
其他,left=elementX-蒙层盒子宽度的一半
y轴
如 elementY<蒙层盒子高度的一半,表示超出上面,让top=0
如elementY>盒子容器的高度-蒙层盒子高度的一半,表示超出右边,让top=盒子容器的宽度-蒙层盒子的宽度。
其他,top=elementY-蒙层盒子高度的一半
4.定义放大图的x,y,让x=-left2让y=-top2
<template> <!-- 测试 --> <!-- <h1> div.middle内移动坐标x:{{ elementX }},y:{{ elementY }},是否在盒子外移动:{{ isOutside }} </h1> --> <div class="goods-image"> <!-- 放大镜图片 --> <div class="large" v-show="!isOutside" :style="[ { backgroundImage: `url(${list[currIndex]})`, backgroundPosition: `${bg.x}px ${bg.y}px`, }, ]" ></div> <!-- 左侧-大图 --> <div class="middle" ref="target"> <img :src="list[currIndex]" alt="" /> <!-- 正方体蒙层滑块 --> <div v-show="!isOutside" class="layer" :style="{ left: `${pos.left}px`, top: `${pos.top}px` }" ></div> </div> <!-- 右侧-小图片列表 --> <ul class="small"> <li v-for="(img, i) in list" :key="i" @mouseenter="currIndex = i"> <img :src="img" alt="" /> </li> </ul> </div> </template> <script> import { ref, watch } from 'vue' import { useMouseInElement } from '@vueuse/core' export default { name: 'GoodsImage', props: { list: { type: Array, default: () => [] } }, setup () { // 需求:鼠标经过某个小图,在左侧显示它的大图 /** * 1. 鼠标经过获取当前图片的索引值 * 2. 根据索引值获取当前图片的url */ const currIndex = ref(0) /** * 放大镜实现: * 前置知识:浏览器坐标系从左上角开始(x:0,y:0) * * 1. 获取元素内鼠标移动的坐标 * 2. 监听元素内鼠标移动的坐标变化=》控制蒙层移动=》计算蒙层:left和top的值 * 结论: * 1. 蒙层移动的范围: 100< pos <300 * 2. 蒙层位置计算公式:left = elementX - 100 | top = elementY - 100 */ // target 限定鼠标移动范围 const target = ref(null) // 蒙层位置变量 const pos = ref({ left: 0, top: 0 }) // 蒙层区域图片放大(2X) const bg = ref({ x: 0, y: 0 }) // elementX, elementY target元素范围内的坐标值 const { elementX, elementY, isOutside } = useMouseInElement(target) watch([elementX, elementY], () => { // 横向移动x轴 if (elementX.value < 100) { // 超出置0(左边) pos.value.left = 0 } else if (elementX.value > 300) { // 超出置200(右边) pos.value.left = 200 } else { pos.value.left = elementX.value - 100 } // 纵向移动y轴 if (elementY.value < 100) { // 超出置0(上) pos.value.top = 0 } else if (elementY.value > 300) { // 超出置200(下) pos.value.top = 200 } else { pos.value.top = elementY.value - 100 } // 计算背景图放大 bg.value.x = -pos.value.left * 2 bg.value.y = -pos.value.top * 2 }) return { currIndex, target, elementX, elementY, isOutside, pos, bg } } } </script> <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; z-index: 500; 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; position: absolute; } } .small { width: 80px; li { width: 68px; height: 68px; margin-left: 12px; margin-bottom: 15px; cursor: pointer; &:hover, &.active { border: 2px solid @xtxColor; } } } } </style>