Vue3+TS项目中实现图片放大镜效果

该文章提供了一段Vue3代码示例,展示了如何创建一个图片预览功能。当鼠标悬停在小图片上时,会显示一个遮罩层和大图。通过监听鼠标移动事件,动态调整遮罩层和大图的位置,模拟图片预览的效果。代码中包含了HTML结构、CSS样式和JavaScript逻辑。
摘要由CSDN通过智能技术生成

我们先看看效果图

 废话不多说,直接上代码(注释都在代码中)

要求:你需要准备一个800*800的图片(下面代码使用的是网络图片,如果图片失效,请手动更换)

或者一个400*400的图片用来展示小图一个800*800的图片用来展示大图

下面的代码只是实现了静态样式,如果你需要实现更多功能请独自完成开发。

可以将获取元素的as类型断言的语句去掉,这样就可以在js的环境下运行

<template>
  <div class="fangda">
    <div class="contenr">
      <!-- 存放大图,小图和遮罩层 -->
      <div class="simg">
        <img src="@/assets/styles/images/列表图片1.jpg" alt="">
        <!-- 遮罩层 -->
        <div class="box"></div>
      </div>
      <!-- 大图 -->
      <div class="bimg">
        <img class="p-img" src="@/assets/styles/images/列表图片1.jpg" alt="">
      </div>
    </div>
    <!-- 右侧图片列表 -->
    <div class="list">
      <ul>
        <li v-for="item in 5" :key="item"><img src="@/assets/styles/images/列表图片1.jpg" alt=""></li>
      </ul>
    </div>
  </div>
</template>
  
<script setup lang='ts'>
import { onMounted } from 'vue'
onMounted(() => {
  // 利用vue3的钩子函数,获取DOM元素
  const { simg, box, bimg, pImg, list } = getElements()

  // 获取元素
  function getElements() {
    // 如果你是js的项目可以把as 语句去掉
    const simg = document.querySelector('.simg') as HTMLDivElement
    const box = document.querySelector('.box') as HTMLDivElement
    const bimg = document.querySelector('.bimg') as HTMLDivElement
    const pImg = document.querySelector('.p-img') as HTMLImageElement
    const list = document.querySelector('.list') as HTMLDivElement
    return { simg, box, bimg, pImg, list }
  }
  // 当鼠标滑过左侧小图片的时候显示遮罩层和大盒子
  const handleMouseOver = () => {
    box.style.display = 'block'
    bimg.style.display = 'block'
    list.style.display = 'none'
  }
  // 鼠标离开左侧小图片的时候隐藏遮罩层和大盒子
  const handleMouseLeave = () => {
    box.style.display = 'none';
    bimg.style.display = 'none';
    list.style.display = 'block'
  }

  const handleMouseMove = (e: MouseEvent) => {
    // 阴影的距离:鼠标的位置-盒子的位置-阴影宽高的一半
    let X: number = e.clientX - simg.offsetLeft - box.offsetWidth / 2
    let Y: number = e.clientY - bimg.offsetTop - box.offsetHeight / 2
    // 让阴影移动
    // 位置限定
    const maxWidth = simg.offsetWidth - box.offsetWidth;
    const maxHeight = simg.offsetHeight - box.offsetHeight;
    X = Math.max(0, Math.min(X, maxWidth));
    Y = Math.max(0, Math.min(Y, maxHeight));

    // 让遮罩层动起来
    box.style.left = X + 'px'
    box.style.top = Y + 'px'
    // 让大盒子中的的图片动起来
    // 因为大盒子中图片和小盒子中图片比是2:1所以需要大盒子移动的唯一是小盒子的2倍,并且方向相反
    pImg.style.left = -(2 * X) + 'px'
    pImg.style.top = -(2 * Y) + 'px'
  }
  // 给小盒子绑定事件
  simg.addEventListener('mouseover', handleMouseOver)
  simg.addEventListener('mouseleave', handleMouseLeave)
  simg.addEventListener('mousemove', handleMouseMove)
})

</script>
  
<style lang="less" scoped>
.fangda {
  display: flex;

  .contenr {
    display: flex;

    .simg {
      width: 400px;
      height: 400px;
      position: relative;

      img {
        width: 100%;
        height: 100%;
      }

      .box {
        width: 200px;
        height: 200px;
        background-color: #333;
        opacity: 0.1;
        display: none;
        position: absolute;
        top: 0;
        left: 0;
      }
    }

    .bimg {
      height: 400px;
      width: 400px;
      margin-left: 15px;
      overflow: hidden;
      display: none;
      position: relative;
      background-color: aqua;
      // 让大图片位于最上方
      z-index: 9999;

      .p-img {
        // 根据实际需要设置这两行代码
        max-width: 800px;
        max-height: 800px;
        // 我的项目中受到全局样式影响,所以设置了上面的两行代码
        position: absolute;
        top: 0;
        left: 0;
      }
    }
  }

  .list {

    ul {
      list-style: none;
      width: 80px;
      height: 400px;
      padding: 0;
      margin: 0;

      li {
        width: 64px;
        height: 64px;
        margin-bottom: 15px;
        margin-left: 12px;
        border-color: #27ba9b;
        border: 2px solid transparent;

        img {
          width: 100%;
          height: 100%;
          vertical-align: middle;
        }
      }
    }
  }
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值