The effect

Core problem solving

1. How to achieve the mouse following effect of the left mask 2. How to show the zoom effect

infrastructure

<template>
  <div class="goods-image">
    <div class="middle">
      <img src="https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg" alt="">
    </div>
    <ul class="small">
      <li v-for="i in 4" :key="i">
        <img src="https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg" alt="">
      </li>
    </ul>
  </div>
</template>

<style scoped lang="less">
.goods-image {
  width: 480px;
  height: 400px;
  position: relative;
  display: flex;
  .middle {
    width: 400px;
    height: 400px;
    background: #f5f5f5;
  }
  .small {
    width: 80px;
    li {
      width: 68px;
      height: 68px;
      margin-left: 12px;
      margin-bottom: 15px;
      cursor: pointer;
      &:hover, &.active {
        border: 2pxsolid @xtxColor; }}}}</style>
Copy the code

Realize the mouse following effect of the left mask

Follow the way of thinking

To prepare the mask container to be moved, change its top, left position by absolute positioning to move real-time monitor mouse position, let the container follow the mouse

The mask layer

<div class="middle">
    <img src="https://yanxuanitem.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg" alt="">
+   <div class="layer"></div>
</div>

<style scoped lang="less">
  .middle {
    width: 400px;
    height: 400px;
+    position: relative;
+    cursor: move;
+    .layer{+width: 200px;
+      height: 200px;
+      background: rgba(0.0.0.2);
+      left: 0;
+      top: 0;
+      position: absolute; +}}</style>
Copy the code

The mouse follow

In @vueuse, there is a tool method :useMouseInElement vueuse.org/core/usemou…

import { useMouseInElement } from '@vueuse/core'

setup () {
  // Calculate the mouse position based on which element
  const target = ref(null)
  const { elementX, elementY, isOutside } = useMouseInElement(target)
  return { currIndex, target, elementX, elementY, isOutside }
}
Copy the code
+ <div class="middle" ref="target">/ / plus the targetCopy the code

sertup () {
  ...
  const layerStyle = reactive({ top: '0px'.left: '0px' })
  watch([elementX,elementY,isOutside], () = > {
  // top, left is used to determine the absolute position of the lower mask element
  const top = elementY.value - 100
  const left = elementX.value - 100

  // Assign positions to mask elements
  layerStyle.top = top + 'px'
  layerStyle.left = left + 'px'
  })
  return{... Omit, layerStyle}}Copy the code

In the template

+ <div class="layer" :style="layerStyle"></div>
Copy the code



The mask layer can now move with it

Position correction

The mask layer cannot exit the image area

// The position of the mask element cannot be moved out of the middle image range
if (top > 200) top = 200
if (top < 0) top = 0
if (left > 200) left = 200
if (left < 0) left = 0
Copy the code

Effect of implementation

Show magnification

Enlarge mentality

Change background-position-x,background-position-y add responsive data largeStyle to calculate the value of background-position according to the position of the current left mask

Magnification layer

<div class="middle">
+   <div class="large" :style="{backgroundImage: `url(https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg)`}"></div>
    <img src="https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg" alt="">
    <div class="layer" :style="layerStyle"></div>
</div>

<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; +}</style>
Copy the code

Zoom in implementation

setup () {
  ...
+ const largeStyle = reactive({
+   'background-position-x': '0px',
+   'background-position-y': '0px'
+ })
  watch([elementX,elementY,isOutside], () = > {
    // top, left is used to determine the absolute position of the lower mask element
    let top = elementY.value - 100
    let left = elementX.value - 100
    if (top > 200) top = 200
    if (top < 0) top = 0
    if (left > 200) left = 200
    if (left < 0) left = 0
    // Assign positions to mask elements
    layerStyle.top = top + 'px'
    layerStyle.left = left + 'px'
+   largeStyle['background-position-x'] = -2 * left + 'px'
+   largeStyle['background-position-y'] = -2 * top + 'px'
  })
  return {+largeStyle}
}
Copy the code

In the template

+ <div class="large" :style="{backgroundImage: `url(...) `,... largeStyle}"></div>
Copy the code

Effect to complete

Mouse in display to remove hiding

Use it directly

<div
+ v-show=! "" isOutside"
  class="large"
  :style="{backgroundImage: `url(...) `,... largeStyle}">
</div>
<img src="https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg" alt="">
<div 
+ v-show=! "" isOutside" 
  class="layer" 
  :style="layerStyle">
</div>
Copy the code

The final result