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

JavaScript Canvas draws dynamic wireframe effect

This article shares the specific code of JavaScri...

Detailed explanation of basic syntax and data types of JavaScript

Table of contents Importing JavaScript 1. Interna...

Detailed explanation of how to monitor MySQL statements

Quick Reading Why do we need to monitor SQL state...

HTML head tag detailed introduction

There are many tags and elements in the HTML head ...

Simple steps to encapsulate components in Vue projects

Table of contents Preface How to encapsulate a To...

CSS uses BEM naming convention practice

When you see a class, what information do you wan...

Basic operations on invisible columns in MySQL 8.0

Table of contents 01 Create invisible columns 02 ...

Stealing data using CSS in Firefox

0x00 Introduction A few months ago, I found a vul...

Detailed explanation of Docker usage under CentOS8

1. Installation of Docker under CentOS8 curl http...

Use of Linux crontab command

1. Command Introduction The contab (cron table) c...

HTML small tag usage tips

Phrase elements such as <em></em> can ...