Example code of Vue3 encapsulated magnifying glass component

Example code of Vue3 encapsulated magnifying glass component

Component Infrastructure

There is a complete code at the end that can be copied and used directly

Purpose: Encapsulate the image preview component to achieve the mouse hover switching effect

Landing code:

<template>
  <div class="goods-image">
    <div class="middle">
      <img :src="images[currIndex]" alt="">
    </div>
    <ul class="small">
      <li v-for="(img,i) in images" :key="img" :class="{active:i===currIndex}">
        <img @mouseenter="currIndex=i" :src="img" alt="">
      </li>
    </ul>
  </div>
</template>
<script>
import { ref } from 'vue'
export default {
  name: 'GoodsImage',
  props: {
    images:
      type: Array,
      default: () => []
    }
  },
  setup (props) {
    const currIndex = ref(0)
    return { currIndex }
  }
}
</script>
<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: 2px solid @xtxColor;
      }
    }
  }
}
</style>

Image Magnifier

Purpose: To realize the image magnifying glass function

step:

  • First prepare the large image container and the mask container
  • Then use the useMouseInElement method of @vueuse/core to get the element-based offset
  • Calculate the mask container position and the large container background position and expose the data to the template for use

Landing code:

<template>
  <div class="goods-image">
+ // Achieve the large image layout effect on the right (enlarge the background image 4 times)
+ <div class="large" :style="[{backgroundImage:`url(${images[currIndex]})`}]"></div>
    <div class="middle">
      <img :src="images[currIndex]" alt="">
+ // Prepare the mask container to be moved + <div class="layer"></div>
    </div>
    <ul class="small">
      <li v-for="(img,i) in images" :key="img" :class="{active:i===currIndex}">
        <img @mouseenter="currIndex=i" :src="img" alt="">
      </li>
    </ul>
  </div>
</template>
<script>
import { ref } from 'vue'
export default {
  name: 'GoodsImage',
  props: {
    images:
      type: Array,
      default: () => []
    }
  },
  setup (props) {
    const currIndex = ref(0)
    return { currIndex }
  }
}
</script>
<style scoped lang="less">
.goods-image {
  width: 480px;
  height: 400px;
  position: relative;
  display: flex;
+ z-index: 500;
+ // Right large image style+ .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;
+ // Mask style+ .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>

Install vueuse

npm i @vueuse/[email protected]

Currently version 5.3.0 is relatively stable

Basic usage of the listening method provided by vueuse to enter the specified range

import { useMouseInElement } from '@vueuse/core'
const { elementX, elementY, isOutside } = useMouseInElement(target)

The method parameter target represents the monitored DOM object; the return values ​​elementX and elementY represent the position information of the upper left corner of the monitored DOM, left and top; isOutside represents whether it is within the range of the DOM, true means it is outside the range. false means within the range.

Functionality

<div v-if="isShow" class="large" :style="[{ backgroundImage: `url(${images[currIndex]})` }, bgPosition]"></div>
<div class="middle" ref="target">
   <img :src="images[currIndex]" alt="" />
   <div class="layer" v-if="isShow" :style="[position]"></div>
</div>

setup () {
// The monitored area const target = ref(null)
// Control the display and hiding of the mask layer and preview image const isShow = ref(false)
// Define the coordinates of the mask const position = reactive({
      left: 0,
      top: 0
})
// Coordinates of the preview image on the right const bgPosition = reactive({
      backgroundPositionX: 0,
      backgroundPositionY: 0
})

return { position, bgPosition, target, isShow }
}
const { elementX, elementY, isOutside } = useMouseInElement(target)
  // Listen for value changes based on the listener watch([elementX, elementY, isOutside], () => {
    // Control display and hiding through flags isShow.value = !isOutside.value
    if (isOutside.value) return
    // X-axis coordinate range control if (elementX.value < 100) {
      // Left side position.left = 0
    } else if (elementX.value > 300) {
      // Right side position.left = 200
    } else {
      // Middle position.left = elementX.value - 100
    }
    // Y direction coordinate range control if (elementY.value < 100) {
      position.top = 0
    } else if (elementY.value > 300) {
      position.top = 200
    } else {
      position.top = elementY.value - 100
    }
    // Calculate the moving distance of the preview image bgPosition.backgroundPositionX = -position.left * 2 + 'px'
    bgPosition.backgroundPositionY = -position.top * 2 + 'px'
    // Calculate the position of the mask layer position.left = position.left + 'px'
    position.top = position.top + 'px'
  })

Complete code

<template>
  <div class="goods-image">
    <div v-if="isShow" class="large" :style="[{ backgroundImage: `url(${images[currIndex]})` }, bgPosition]"></div>
    <div class="middle" ref="target">
      <img :src="images[currIndex]" alt="" />
      <div class="layer" v-if="isShow" :style="[position]"></div>
    </div>
    <ul class="small">
      <li v-for="(img, i) in images" :key="img" :class="{ active: i === currIndex }">
        <img @mouseenter="currIndex = i" :src="img" alt="" />
      </li>
    </ul>
  </div>
</template>
<script>
import { ref, watch, reactive } from 'vue'
import { useMouseInElement } from '@vueuse/core'
export default {
  name: 'GoodsImage',
  props: {
    images:
      type: Array,
      default: () => []
    }
  },
  setup (props) {
    const currIndex = ref(0)
    const target = ref(null)
    const isShow = ref(false)
    const position = reactive({
      left: 0,
      top: 0
    })
    const bgPosition = reactive({
      backgroundPositionX: 0,
      backgroundPositionY: 0
    })
    const { elementX, elementY, isOutside } = useMouseInElement(target)
    watch([elementX, elementY, isOutside], () => {
      isShow.value = !isOutside.value
      if (isOutside.value) return
      if (elementX.value <= 100) {
        position.left = 0
      } else if (elementX.value >= 300) {
        position.left = 200
      } else {
        position.left = elementX.value - 100
      }
      if (elementY.value <= 100) {
        position.top = 0
      } else if (elementY.value >= 300) {
        position.top = 200
      } else {
        position.top = elementY.value - 100
      }
      bgPosition.backgroundPositionX = -position.left * 2 + 'px'
      bgPosition.backgroundPositionY = -position.top * 2 + 'px'
      position.left += 'px'
      position.top += 'px'
    })
    return { currIndex, target, isShow, position, bgPosition }
  }
}
</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>

Summarize

This is the end of this article about the vue3 encapsulated magnifying glass component. For more relevant vue3 encapsulated magnifying glass component content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vue realizes the product magnifying glass effect
  • Vue3 realizes the image magnifying glass effect
  • Vue implements the magnifying glass function of the product details page
  • Vue implements the magnifying glass effect of tab switching
  • Vue implements a simple magnifying glass effect
  • Vue implements a search box with a magnifying glass
  • Vue3.0 handwriting magnifying glass effect
  • Vue implements magnifying glass effect
  • A handwritten vue magnifying glass effect
  • Vue3 encapsulates the magnifying glass effect component of Jingdong product details page

<<:  MySQL master-slave replication configuration process

>>:  How to use sed command to efficiently delete specific lines of a file

Recommend

Windows cannot start MySQL service and reports error 1067 solution

Suddenly when I logged into MySQL, it said that a...

Implementing a web calculator based on JavaScript

This article shares the specific code of JavaScri...

Vue folding display multi-line text component implementation code

Folding display multi-line text component Fold an...

npm Taobao mirror modification explanation

1. Top-level usage 1. Install cnpm npm i -g cnpm ...

How to set up swap partition SWAP in Linux 7.7

The Swap partition of the Linux system, that is, ...

Analysis of implicit bug in concurrent replication of MySQL 5.7

Preface Most of our MySQL online environments use...

Web Design Tutorial (2): On Imitation and Plagiarism

<br />In the previous article, I introduced ...

Detailed explanation of the abbreviation of state in react

Preface What is state We all say that React is a ...

Example code for implementing verification code login in SMS API in Node

1. Node server setup + database connection The op...

Element-ui's built-in two remote search (fuzzy query) usage explanation

Problem Description There is a type of query call...

Docker deployment and installation steps for Jenkins

First, we need a server with Docker installed. (I...

CSS float property diagram float property details

Using the CSS float property correctly can become...

CentOS 8 officially released based on Red Hat Enterprise Linux 8

The CentOS Project, a 100% compatible rebuild of ...

MySQL transaction control flow and ACID characteristics

Table of contents 1. ACID Characteristics Transac...