• vue3中实现放大镜效果,使用ref获取节点元素


    效果如下: 

     首先,有一个放大镜的DOM结构

    1. <template>
    2. <div class="spec-preview">
    3. <img :src="imgObj.imgUrl" />
    4. <div class="event">div>
    5. <div class="big">
    6. <img :src="imgObj.imgUrl" />
    7. div>
    8. <div class="mask">div>
    9. div>
    10. template>

    这里img的src是通过父组件传过来的imgList来展示的,可以换成自己的任意图

    交代一下:遮罩层和展示图都是正方形的,而且遮罩层的宽高都是展示图的一半

    分别要绑定鼠标移动事件,和获取两个元素节点,分别是遮罩层和放大图

    1. <template>
    2. <div class="spec-preview">
    3. <img :src="imgObj.imgUrl" />
    4. <div class="event" @mousemove="handler">div>
    5. <div class="big">
    6. <img :src="imgObj.imgUrl" ref="big" />
    7. div>
    8. <div class="mask" ref="mask">div>
    9. div>
    10. template>

    vue3中如何获得ref绑定的节点元素呢?

    首先,要知道在vue2中获取ref节点元素是很简单的,只需要this.$refs.mask即可。但是vue3中是没有this.$refs的。 

    为了结构清楚,我把其他不涉及这个案例的代码都删掉了。handlerMask和handlerBig就是我们想要获取的节点。

    获取到节点后,就可以写相应的放大器实现代码了

    首先要获取event的offserX也就是我们鼠标距离左侧边框的距离 ,然后还需要减去遮罩层本身宽度的一半,高度同理。并且添加约束条件,让这个遮罩层不能出展示区域。最后就只需要修改相应元素的left和top属性即可了(当然,这里肯定是要用到绝对定位的,子绝父相)

    1. function handler(event) {
    2. let handlerMask = mask.value;
    3. let left = event.offsetX - handlerMask.offsetWidth / 2;
    4. let top = event.offsetY - handlerMask.offsetHeight / 2;
    5. // 约束范围
    6. if (left <= 0) left = 0;
    7. if (left >= handlerMask.offsetWidth) left = handlerMask.offsetWidth;
    8. if (top <= 0) top = 0;
    9. if (top >= handlerMask.offsetHeight) top = handlerMask.offsetHeight;
    10. // 修改元素的left|top属性值
    11. handlerMask.style.left = left + "px";
    12. handlerMask.style.top = top + "px";
    13. // 修改放大图
    14. let handlerBig = big.value;
    15. handlerBig.style.left = -2 * left + "px";
    16. handlerBig.style.top = -2 * top + "px";
    17. }

    这里稍微有疑惑的可能就是放大图为什么是-2去相乘。 首先根据前面的介绍,我们的展示图和放大图的大小是一致的,都是正方形。而遮罩层的宽高都是其一半。所以要把相应的遮罩层的图片放大,就是简单的乘以2即可。那为什么是负数。这就是涉及到放大图的移动方向了。我们遮罩层向左移动,起始放大图是相应的向右移动的。

     

    1. .event {
    2. width: 100%;
    3. height: 100%;
    4. position: absolute;
    5. top: 0;
    6. left: 0;
    7. z-index: 998;
    8. }
    9. .mask {
    10. width: 50%;
    11. height: 50%;
    12. background-color: rgba(0, 255, 0, 0.3);
    13. position: absolute;
    14. left: 0;
    15. top: 0;
    16. display: none;
    17. }
    18. .big {
    19. width: 100%;
    20. height: 100%;
    21. position: absolute;
    22. top: -1px;
    23. left: 100%;
    24. border: 1px solid #aaa;
    25. overflow: hidden;
    26. z-index: 998;
    27. display: none;
    28. background: white;
    29. }
    30. img {
    31. width: 200%;
    32. max-width: 200%;
    33. height: 200%;
    34. position: absolute;
    35. left: 0;
    36. top: 0;
    37. }

    根据上面的展示(我把big里面的overflow:hidden去掉后的),可以看到,其实图片的大小的是展示图和放大镜大小的2倍,超出部分是隐藏的。也就是向着相反的方向移动,使得我们遮罩层的区域放大后正好在放大镜的展示区域中。

    完整代码如下:

    1. <template>
    2. <div class="spec-preview">
    3. <img :src="imgObj.imgUrl" />
    4. <div class="event" @mousemove="handler">div>
    5. <div class="big">
    6. <img :src="imgObj.imgUrl" ref="big" />
    7. div>
    8. <div class="mask" ref="mask">div>
    9. div>
    10. template>
    11. <script>
    12. import { computed, getCurrentInstance, onMounted, ref } from "vue";
    13. export default {
    14. name: "ZoomIndex",
    15. props: ["skuImageList"],
    16. setup(props) {
    17. const internalInstance = getCurrentInstance(); //当前组件实例
    18. const $bus = internalInstance.appContext.config.globalProperties.$bus;
    19. // console.log(props);
    20. let currentIndex = ref(0);
    21. let mask = ref(null);
    22. let big = ref(null);
    23. let imgObj = computed({
    24. get() {
    25. return props.skuImageList[currentIndex.value] || {};
    26. },
    27. });
    28. function handler(event) {
    29. let handlerMask = mask.value;
    30. let left = event.offsetX - handlerMask.offsetWidth / 2;
    31. let top = event.offsetY - handlerMask.offsetHeight / 2;
    32. // 约束范围
    33. if (left <= 0) left = 0;
    34. if (left >= handlerMask.offsetWidth) left = handlerMask.offsetWidth;
    35. if (top <= 0) top = 0;
    36. if (top >= handlerMask.offsetHeight) top = handlerMask.offsetHeight;
    37. // 修改元素的left|top属性值
    38. handlerMask.style.left = left + "px";
    39. handlerMask.style.top = top + "px";
    40. // 修改放大图
    41. let handlerBig = big.value;
    42. handlerBig.style.left = -2 * left + "px";
    43. handlerBig.style.top = -2 * top + "px";
    44. }
    45. onMounted(() => {
    46. // 全局事件总线,获取兄弟组件传递过来的索引值
    47. $bus.on("getIndex", (index) => {
    48. // 修改当前响应式数据
    49. currentIndex.value = index.value;
    50. });
    51. });
    52. return {
    53. currentIndex,
    54. imgObj,
    55. handler,
    56. mask,
    57. big,
    58. };
    59. },
    60. };
    61. script>
    62. <style lang="less">
    63. .spec-preview {
    64. position: relative;
    65. width: 400px;
    66. height: 400px;
    67. border: 1px solid #ccc;
    68. img {
    69. width: 100%;
    70. height: 100%;
    71. }
    72. .event {
    73. width: 100%;
    74. height: 100%;
    75. position: absolute;
    76. top: 0;
    77. left: 0;
    78. z-index: 998;
    79. }
    80. .mask {
    81. width: 50%;
    82. height: 50%;
    83. background-color: rgba(0, 255, 0, 0.3);
    84. position: absolute;
    85. left: 0;
    86. top: 0;
    87. display: none;
    88. }
    89. .big {
    90. width: 100%;
    91. height: 100%;
    92. position: absolute;
    93. top: -1px;
    94. left: 100%;
    95. border: 1px solid #aaa;
    96. // overflow: hidden;
    97. z-index: 998;
    98. display: none;
    99. background: white;
    100. img {
    101. width: 200%;
    102. max-width: 200%;
    103. height: 200%;
    104. position: absolute;
    105. left: 0;
    106. top: 0;
    107. }
    108. }
    109. .event:hover ~ .mask,
    110. .event:hover ~ .big {
    111. display: block;
    112. }
    113. }
    114. style>

     

  • 相关阅读:
    怎样的数据采集系统才算合格
    SimpleChannelInboundHandler使用总结
    11.26
    2024“钉耙编程”中国大学生算法设计超级联赛(7)
    为什么选择 TypeScript
    Spring——》feign下载文件
    装机必备!这5款免费软件,你值得拥有!
    Linux内核开发——自定义字符设备
    在Linux上安装RStudio工具并实现本地远程访问【内网穿透】
    算法题:买卖股票的最佳时机 II (贪心算法解决股票问题)
  • 原文地址:https://blog.csdn.net/m0_56698268/article/details/126686644