前端小案例-放大镜效果实现

79 阅读1分钟

记录一下最近做的一个小功能,放大镜效果实现。 首先准备一个静态页面,包含以下模块:

    <div class="middle" ref="target">
      <img :src="imageList[0]" alt="" />
      <!-- 蒙层小滑块 -->
      <div class="layer" :style="{ left: `0px`, top: `0px` }"></div>
    </div>
    <!-- 小图列表 -->
    <ul class="small">
      <li v-for="(img, i) in imageList" :key="i">
        <img :src="img" alt="" />
      </li>
    </ul>
    <!-- 放大镜大图 -->
    <div class="large" :style="[
      {
        backgroundImage: `url(${imageList[0]})`,
        backgroundPositionX: `0px`,
        backgroundPositionY: `0px`,
      },
    ]" v-show="false"></div>
  </div>

得到的静态页面如下:

图片.png 接着就开始写交互逻辑:

  1. 第一步先去写一个鼠标进入右侧小图,使得右侧小图边框提示变绿的效果。
//逻辑:1.通过v-for获取鼠标进入的标签序号,然后保存序号,再动态加class
<!-- 小图列表 -->
<script setup>
let curIdx = ref(0)
</script>
<ul class="small">
    <li v-for="(img, i) in imageList" :key="i" @mouseenter="curIdx = i" :class="{ active: curIdx === i }">
        <img :src="img" alt="" />
    </li>
</ul>
  1. 第二步将左侧大图的img标签的src动态绑定成右侧激活的小图src地址
<!-- 左侧大图-->
<div class="middle" ref="target">
    <img :src="imageList[curIdx]" alt="" />
    <!-- 蒙层小滑块 -->
    <div class="layer" :style="{ left: `${layer_x}px`, top: `${layer_y}px` }"></div>
</div>
  1. 获取鼠标位置,在这里我使用的是vueUse的APIuseMouseInElement,结构该方法返回的值,得到需要的三个值x, y, isOutside。然后控制蒙层小滑块随着鼠标移动,
<script setup>
// 2. 获取鼠标相对位置
const target = ref(null)
const { elementX, elementY, isOutside } = useMouseInElement(target)

// 3. 控制滑块跟随鼠标移动(监听elementX/Y变化,一旦变化 重新设置left/top)
const left = ref(0)
const top = ref(0)

const positionX = ref(0)
const positionY = ref(0)
watch([elementX, elementY, isOutside], () => {
  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>
<!-- 蒙层小滑块 -->
<div class="layer" v-show="!isOutside" :style="{ left: `${left}px`, top: `${top}px` }"></div>
 

4.实现放大镜逻辑,实际就是用一个两倍于左侧大图的div标签装放大镜的图,将背景图设置成左侧大图的url,然后用backgroundPositionX/Y来控制放大镜的显示。

<script setup>
  // 控制大图的显示
  positionX.value = -left.value * 2
  positionY.value = -top.value * 2
</script>
<!-- 放大镜大图 -->
<div class="large" :style="[
  {
    backgroundImage: `url(${imageList[0]})`,
    backgroundPositionX: `${positionX}px`,
    backgroundPositionY: `${positionY}px`,
  },
]" v-show="!isOutside"></div>
</div>