• Vue中实现放大镜效果


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

     这里我们没有使用原生的 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

    1. <template>
    2. <div class="goods-image">
    3. <div v-show="show" class="large" :style="[{backgroundImage:`url(${images[currIndex]})`}, largePosition]">div>
    4. <div class="middle" ref="target">
    5. <img :src="images[currIndex]" alt="">
    6. <div v-show="show" class="layer" :style="layerPosition">div>
    7. div>
    8. <ul class="small">
    9. <li v-for="(item, i) in images" :key="item" :class="{active: currIndex===i}">
    10. <img @mouseenter="currIndex=i" :src="item" alt="">
    11. li>
    12. ul>
    13. div>
    14. template>
    15. <script>
    16. import { reactive, ref, watch } from 'vue'
    17. import { useMouseInElement } from '@vueuse/core'
    18. export default {
    19. name: 'GoodsImage',
    20. props: {
    21. images: {
    22. type: Array,
    23. default: () => []
    24. }
    25. },
    26. setup (props) {
    27. const currIndex = ref(0)
    28. // 1. 是否显示遮罩和大图
    29. const show = ref(false)
    30. // 2. 遮罩的坐标(样式)
    31. const layerPosition = reactive({
    32. top: 0,
    33. left: 0
    34. })
    35. // 3. 大图的背景坐标(样式)
    36. const largePosition = reactive({
    37. backgroundPositionX: 0,
    38. backgroundPositionY: 0
    39. })
    40. // 4. 获取监听元素的实例对象, 使用useMouseInElement函数进行获取坐标
    41. const target = ref(null)
    42. const { elementX, elementY, isOutside } = useMouseInElement(target)
    43. // 5. 监听元素坐标值的变化
    44. watch([elementX, elementY, isOutside], () => {
    45. show.value = !isOutside.value
    46. const position = { X: 0, Y: 0 }
    47. if (elementX.value < 100) position.X = 0
    48. else if (elementX.value > 300) position.X = 200
    49. else position.X = elementX.value - 100
    50. if (elementY.value < 100) position.Y = 0
    51. else if (elementY.value > 300) position.Y = 200
    52. else position.Y = elementY.value - 100
    53. layerPosition.left = position.X + 'px'
    54. layerPosition.top = position.Y + 'px'
    55. largePosition.backgroundPositionX = -2 * position.X + 'px'
    56. largePosition.backgroundPositionY = -2 * position.Y + 'px'
    57. })
    58. return { currIndex, show, layerPosition, largePosition, target }
    59. }
    60. }
    61. script>
    62. <style scoped lang="less">
    63. .goods-image {
    64. width: 480px;
    65. height: 400px;
    66. position: relative;
    67. display: flex;
    68. z-index: 500;
    69. .large {
    70. position: absolute;
    71. top: 0;
    72. left: 412px;
    73. width: 400px;
    74. height: 400px;
    75. box-shadow: 0 0 10px rgba(0,0,0,0.1);
    76. background-repeat: no-repeat;
    77. background-size: 800px 800px;
    78. background-color: #f8f8f8;
    79. }
    80. .middle {
    81. width: 400px;
    82. height: 400px;
    83. background: #f5f5f5;
    84. position: relative;
    85. cursor: move;
    86. .layer {
    87. width: 200px;
    88. height: 200px;
    89. background: rgba(0,0,0,.2);
    90. left: 0;
    91. top: 0;
    92. position: absolute;
    93. }
    94. }
    95. .small {
    96. width: 80px;
    97. li {
    98. width: 68px;
    99. height: 68px;
    100. margin-left: 12px;
    101. margin-bottom: 15px;
    102. cursor: pointer;
    103. &:hover,&.active {
    104. border: 2px solid @xtxColor;
    105. }
    106. }
    107. }
    108. }
    109. style>
  • 相关阅读:
    Web前端:前端发展趋势的重要性
    Posix与System V IPC
    学习Rust第14天:HashMaps
    使用ceph-deploy部署Ceph集群
    Matlab:合并来自各自变量的日期和时间
    无涯教程-JavaScript - ERFC.PRECISE函数
    一文速学 - PHP7特性
    Pandas get_dummies用法
    构造函数和初始化列表的关系和区别【详解】
    HTML5期末考核大作业——学生网页设计作业源码HTML+CSS+JavaScript 中华美德6页面带音乐文化
  • 原文地址:https://blog.csdn.net/weixin_48524561/article/details/127350141