Vue3 — Own encapsulation similar to the magnifying glass effect components of JINGdong product details page
Finish the basic layout first
To complete the image switching effect, passmouseenter
Event switch image
Be born code
<template>
<div class="goods-image">
<! -- Preview large image -->
<div class="large" v-show="show" :style="[{ backgroundImage: `url(${images[currIndex]})` }, bgPosition]"></div>
<! -- Commodity picture -->
<div class="middle">
<! -- Commodity picture -->
<img ref="target" :src="images[currIndex]" alt="" />
<! Mouse over the image mask -->
<div class="layer" v-show="show" :style="[position]"></div>
</div>
<! -- Thumbnail image -->
<ul class="small">
<li v-for="(img, i) in images" :key="img" :class="{ active: i === currIndex }">
<! -- Move the mouse over the small picture next to the large picture of the commodity and the position of the large picture of the commodity will be displayed -->
<img @mouseenter="currIndex = i" :src="img" alt="" />
</li>
</ul>
</div>
</template>
<script>
import { reactive, ref, watch } from 'vue'
import { useMouseInElement } from '@vueuse/core'
export default {
name: 'GoodsImage'.props: {
images: {
type: Array.default: () = >[]}},setup(props) {
// Control the display and hiding of the preview large image and mask layer
const show = ref(false)
// Control the large picture of the commodity to display that picture
const currIndex = ref(0)
// ref gets the DOM element
const target = ref(null)
// Record the coordinates of the mask translucency map in the commodity picture
const position = reactive({
top: 0.left: 0
})
// Record the coordinates of the area covered by the mask layer in the preview
const bgPosition = reactive({
backgroundPositionX: 0.backgroundPositionY: 0
})
// The method useMouseInElement provided by third-party Vueuse gets the coordinates of the mouse in a certain area
const { elementX, elementY, isOutside } = useMouseInElement(target)
// The listener monitors the coordinates when the mouse enters the large image of the commodity to manipulate the mask layer and preview the effect of the large image
watch([elementX, elementY, isOutside], () = > {
Isisoutside. value: true indicates that the mouse is not in the target element; false indicates that the mouse is in the target element
// True does not record coordinates to avoid performance loss
if (isOutside.value) {
// Do not display mask layer and preview large image without mouse over target element
show.value = false
return
}
// Mouse over the target element to display the mask layer and preview the large image
show.value = true
// Determine the boundary value according to the size of the mask layer and the size of the commodity image
// left boundary values (left and right)
if (elementX.value < 100) {
position.left = 0
} else if (elementX.value > 300) {
position.left = 200
} else {
position.left = elementX.value - 100
}
// Top boundary values (top, bottom)
if (elementY.value < 100) {
position.top = 0
} else if (elementY.value > 300) {
position.top = 200
} else {
position.top = elementY.value - 100
}
// The coordinates of the commodity image covered by the mask layer in the preview big picture, plus units
bgPosition.backgroundPositionY = -position.top * 2 + 'px'
bgPosition.backgroundPositionX = -position.left * 2 + 'px'
// Mask layer relative to the upper left corner of the commodity picture, plus units
position.top += 'px'
position.left += 'px'
})
// return it to the template
return { currIndex, show, target, 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;
position: relative;
cursor: move;
.layer {
width: 200px;
height: 200px;
background: rgba(0.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: 2pxsolid @xtxColor; }}}}</style>
Copy the code