<template>
<div v-if="isVisible" ref="imageContainer" class="image-container">
<!-- 图片局部放大的容器 -->
<div
v-show="isZoomed"
:style="zoomedStyle"
class="zoomed-image"
@mousemove="updateZoomedPosition"
@mouseleave="hideZoomedImage"
>
<!-- 放大后的图片 -->
<img :src="src" :style="zoomedImageStyle" alt="Zoomed Image" />
</div>
<!-- 普通显示的图片 -->
<img
:src="src"
:style="imageStyle"
@mousemove="handleMousemove"
@mouseenter="showZoomedImage"
alt="Normal Image"
/>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { useMouseInElement } from '../composables/useMouseInElement';
const props = defineProps({
src: String,
zoom: {
type: Number,
default: 3,
},
});
const imageContainer = ref(null);
const isVisible = ref(true);
const isZoomed = ref(false);
const zoomedPosition = ref({ x: 0, y: 0 });
// 计算放大后图片的样式
const zoomedImageStyle = {
width: `${props.zoom}rem`,
height: 'auto',
position: 'absolute',
transform: `translate(${zoomedPosition.value.x}px, ${zoomedPosition.value.y}px)`,
};
// 计算放大图片容器的样式
const zoomedStyle = {
position: 'absolute',
cursor: 'zoom-in',
};
// 计算普通图片的样式
const imageStyle = {
width: '100%',
height: 'auto',
position: 'relative',
cursor: 'zoom-in',
};
// 显示放大图片
const showZoomedImage = () => {
isZoomed.value = true;
};
// 隐藏放大图片
const hideZoomedImage = () => {
isZoomed.value = false;
};
// 更新放大图片的位置
const updateZoomedPosition = (event) => {
const { width, height } = imageContainer.value.getBoundingClientRect();
const relativeX = event.clientX - imageContainer.value.getBoundingClientRect().left;
const relativeY = event.clientY - imageContainer.value.getBoundingClientRect().top;
zoomedPosition.value = {
x: relativeX - width / (2 * props.zoom),
y: relativeY - height / (2 * props.zoom),
};
};
// 处理鼠标移动事件
const { handleMousemove } = useMouseInElement(imageContainer);
// 组件卸载前清理事件监听
onBeforeUnmount(() => {
handleMousemove.cleanup();
});
</script>
<style scoped>
.image-container {
position: relative;
width: 300px;
height: 200px;
overflow: hidden;
}
.zoomed-image {
overflow: hidden;
}
img {
user-select: n