Vue中实现放大镜效果

2023-11-09

先来看一下我们需要实现的效果是怎样的:

 这里我们没有使用原生的 js 方法去实现, 而是使用的 Vue3 官方推荐的一个工具库 @vueuse/cor 中的 useMouseInElement 方法来实现放大镜的效果

首先来看一下 useMouseInElement 这个方法的返回值有哪些, 会使用到哪些?

 我们会使用到 elementX, elementY, isOutside 这三个值, 它们分别的含义是:

  • elementX 是鼠标在页面的当前 x 轴坐标位置
  • elementY 是鼠标在页面的当前 y 轴坐标位置
  • isOutside 是一个布尔值, false 表示鼠标没有在监听元素内; true 表示鼠标在监听的元素内

 

 放大镜效果的元素就是:

  • 根据鼠标在中图里的当前坐标位置, 通过判断, 将符合条件的鼠标坐标值赋值给遮罩层和大图的坐标

思路分析:

1. 定义一个变量, 控制遮罩层和大图的显示隐藏效果(show)

2. 定义一个对象, 此对象是直接丢到遮罩层元素的 style 属性中; 所以此对象中的只要符合 css 的规则, 此对象的成员为 top 和 left (遮罩层使用了绝对定位, layerPosition)

3. 定义一个对象, 此对象是直接丢到大图元素的 style 属性中; 主要是控制大图的背景图片位置, 所以成员是 backgroundPositionX 和 backgroundPositionY(largePosition)

4. 定义监听页面元素对象的实例(target)

5. 将 target 传给 useMouseInElement , 获取返回值 elementX, elementY, isOutside (它们都是响应式数据)

6. isOutside 动态的修改掉 show 的值

7. 通过条件判断, 动态的修改到 layerPosition 对象和 largePosition 对象的值

8. 将 show, layerPosition, largePosition 抛给页面使用即可 

也就说, elementX = 100 的时候, 遮罩层成的偏移量才可以变化, 这里就是起点

elementX = 300 的时候, 遮罩层的偏移量停止变化, 这里就是终点

所以 elementX = 100 时, layerPosition.left = 0

elementX = 300 时, layerPosition.left = 200

始终要比 elementX 少 100

<template>
  <div class="goods-image">
    <!-- 大图 -->
    <div v-show="show" class="large" :style="[{backgroundImage:`url(${images[currIndex]})`}, largePosition]"></div>

    <!-- 中图 -->
    <div class="middle" ref="target">
      <img :src="images[currIndex]" alt="">
      <!-- 遮罩色块 -->
      <div v-show="show" class="layer" :style="layerPosition"></div>
    </div>

    <!-- 小图 -->
    <ul class="small">
      <li v-for="(item, i) in images" :key="item" :class="{active: currIndex===i}">
        <img @mouseenter="currIndex=i" :src="item" alt="">
      </li>
    </ul>
  </div>
</template>

<script>
import { reactive, ref, watch } from 'vue'
import { useMouseInElement } from '@vueuse/core'
export default {
  name: 'GoodsImage',
  props: {
    images: {
      type: Array,
      default: () => []
    }
  },
  setup (props) {
    const currIndex = ref(0)

    // 1. 是否显示遮罩和大图
    const show = ref(false)

    // 2. 遮罩的坐标(样式)
    const layerPosition = reactive({
      top: 0,
      left: 0
    })

    // 3. 大图的背景坐标(样式)
    const largePosition = reactive({
      backgroundPositionX: 0,
      backgroundPositionY: 0
    })

    // 4. 获取监听元素的实例对象, 使用useMouseInElement函数进行获取坐标
    const target = ref(null)
    const { elementX, elementY, isOutside } = useMouseInElement(target)

    // 5. 监听元素坐标值的变化
    watch([elementX, elementY, isOutside], () => {
      show.value = !isOutside.value
      const position = { X: 0, Y: 0 }

      if (elementX.value < 100) position.X = 0
      else if (elementX.value > 300) position.X = 200
      else position.X = elementX.value - 100

      if (elementY.value < 100) position.Y = 0
      else if (elementY.value > 300) position.Y = 200
      else position.Y = elementY.value - 100

      layerPosition.left = position.X + 'px'
      layerPosition.top = position.Y + 'px'
      largePosition.backgroundPositionX = -2 * position.X + 'px'
      largePosition.backgroundPositionY = -2 * position.Y + 'px'
    })

    return { currIndex, show, layerPosition, largePosition, target }
  }
}
</script>

<style scoped lang="less">
.goods-image {
  width: 480px;
  height: 400px;
  position: relative;
  display: flex;
  z-index: 500;
  .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;
    position: relative;
    cursor: move;
    .layer {
      width: 200px;
      height: 200px;
      background: rgba(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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue中实现放大镜效果 的相关文章

  • 需要使用新应用以打开此steam链接_Steam加好友的N种方法,完美解决教程

    Steam好友打不开 网络无法访问 不知道好友代码是什么在哪里 到底怎么样才能加上正确的好友 这里全部你一一解答 steam好友页面打不开 网络无法访问 很多人可能发现不论是手机端还是客户端都会发生steam社区打不开的情况 其实steam
  • power bi公式运用

    从原有的表中提取数据 生成新的表格 从销售数据汇总表中提取日期成本 生产新的销售成本表 其中 成本 相当于在新表中的名称 沿用旧表表头 销售成本表 SUMMARIZE 销售数据汇总 销售数据汇总 日期 成本 SUM 销售数据汇总 成本 自己

随机推荐

  • 字符串最长重复连续子串

    比如字符串aaaabbbcddc 因为aaaa最长 返回4 本题是面试遇到的真题 需要熟练手写 String数组中 top3的字符与出现的次数 如ababc 输出 a 2 b 2 c 1
  • TCP是如何传输数据的?

    做IT相关的工作 肯定都离不开网络 网络中最重要的协议是TCP 无论是实际工作还是笔试面试 你看哪里能少得了TCP 我考过RFC中与TCP相关的文档 也看过Linux中与TCP相关的源码 也看过不少框架中的TCP相关的代码 对TCP是有点感
  • jq 中如何调用vue的方法

    jq 中如何调用 vue的方法
  • vs2019下内存泄漏检测工具VLD(Visual Leak Detector)的使用

    前言 我们在c 程序开发中经常在使用指针时 会出现内存泄漏的情况 但是很多时候很难定位到是哪个指针出问题了 这时候就需要内存泄漏检查工具 其中比较好用的就是 VLD Visual Leak Detector 下载 VLD下载地址 安装完成后
  • 【华为OD机试c++/java/python】称砝码【 2023 Q1 A卷

    题目描述 现有n种砝码 重量互不相等 分别为 m1 m2 m3 mn 每种砝码对应的数量为 x1 x2 x3 xn 现在要用这些砝码去称物体的重量 放在同一侧 问能称出多少种不同的重量 注 称重重量包括 0 数据范围 每组输入数据满足 1
  • [机缘参悟-65]:《兵者,诡道也》-7-三十六计解读-败战计

    目录 前言 第1章 三十六计 概述 第六套 败战计 第三十一计 美人计 第三十二计 空城计 第三十三计 反间计 第三十四计 苦肉计 第三十五计 连环计 第三十六计 走为上计 前言 兵者 诡道也 兵者 道 的部分 是 道 的另一面 如果 天道
  • Box2D射线和AABB碰撞检测

    box2d使用了一种叫做slab的碰撞检测算法 所谓slab是指两个平行平面之间的空间 由此我们可以把3D空间中的AABB盒子看做是由AABB的3组平行面形成的3个方向的slab的交集 根据这个定义 我们可以得到以下两个结论 1 如果一个点
  • mysql启动报错:Starting MySQL... ERROR! The server quit without updating PID file

    mysql启动时报错 Starting MySQL ERROR The server quit without updating PID file opt mysql data mysql pid 的解决方法 1 可能是 opt mysql
  • [MySQL]一文带你学明白数据库控制语言——DCL

    前言 嗨咯 小伙伴大家好呀 好几天没见了 周末过得怎么样啊 之前学过的SQL语句不会都忘了吧 如果忘了的话大家可以看一下前几期的文章 本期要学习的是SQL语句中的数据库控制语句 DCL 学习完毕之后MySQL中的SQL语句也就结束了 数据库
  • [388]码云使用说明

    码云如何上传项目 码云上传项目 需要3个步骤 在码云网站建立一个空项目 把这个空项目拉到本地 把自己的项目放到这个空项目里面并提交 1 在码云的页面 点击右上角的加号 2 选择新建项目 3 在跳转的页面简要填写项目信息 除了名称和路径 其它
  • 使用HttpClient下载网页

    Httpclient是一个非常好用的第三方库 用于网络编程 可以用来做个爬虫程序什么之类的 安卓中内置的网络编程库就是httpclient 下面就可大家介绍介绍怎么使用httpclient下载新浪首页的源代码 其过程就是首先构建一个http
  • python怎么调用文件_Python如何调用m文件

    Python如何调用m文件 一 安装Python 并正确配置环境变量 matlab2016a只支持python2 7 python3 3 python3 4 python3 4以上版本不支持 推荐学习 Python教程 二 安装Matlab
  • CSS中如何实现一个自适应正方形(宽高相等)的元素?

    聚沙成塔 每天进步一点点 专栏简介 利用 padding 百分比 2 利用 before 伪元素 写在最后 专栏简介 前端入门之旅 探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅
  • cocos2dx中的内存加载PLIST

    今天 加载图片时有问题 myButtonPList loadTextures jineng 02103 png jineng 02103 light png jineng 03101 png UI TEX TYPE PLIST myButt
  • 时间趋势可视化-柱形图

    第1关 大胃王 比赛数据柱形图绘制 绘制柱形图的基本步骤 本关任务 根据实训提供的 大胃王 比赛数据绘制柱形图 熟悉柱形图绘制的基本步骤 coding utf 8 import pandas as pd from matplotlib im
  • 利用CIBERSORT免疫细胞类群分析详细教程

    利用CIBERSORT免疫细胞类群分析详细教程 现在最火的组学技术是什么 无疑便是单细胞测序了 通过单细胞测序 科研人员可以获得比原来更为精细的细胞图谱 但是单细胞测序诸多限制条件 也是不能让大家很好地利用这项技术解决自己的科学问题 除了较
  • 【Qt】通过QtCreator源码学习Qt(十二):Q_D和Q_Q指针(简称“d指针”)详解

    1 Q D和Q Q指针 简称 d指针 简介 参考博客 https www devbean net 2016 11 qt creator source study 07 https blog csdn net rabinsong articl
  • SpringBoot项目中统计所有Controller中的方法

    对接口方法进行抽象 Data public class ControllerMethodItem public String controllerName public String methodName public String req
  • vscode中preLaunchTask“g++”已终止,退出代码为1的解决方案

    问题背景 楼主原来做的项目 电脑中装了MinGW64 还有MinGW的32位版在用vscode时发现出现了 preLaunchTask g 已终止 退出代码为1的问题 找了好久 解决了问题 launch json 注释的位置 这里修改GDB
  • Vue中实现放大镜效果

    先来看一下我们需要实现的效果是怎样的 这里我们没有使用原生的 js 方法去实现 而是使用的 Vue3 官方推荐的一个工具库 vueuse cor 中的 useMouseInElement 方法来实现放大镜的效果 首先来看一下 useMous