使用vue3的setup写法,在不使用插件和其他库的情况下,写一个好用的电商放大镜组件,放大镜可以自己传入放大的比例和大小
时间: 2023-07-16 12:16:31 浏览: 96
好的,下面是一个简单的电商放大镜组件的实现:
```vue
<template>
<div class="magnifier-container" ref="magnifierContainer">
<div class="magnifier-preview" ref="previewBox">
<img :src="imageSrc" ref="previewImg" />
<div
class="magnifier-lens"
:style="{ width: lensSize + 'px', height: lensSize + 'px', backgroundImage: 'url(' + imageSrc + ')' }"
ref="lens"
></div>
</div>
<div
class="magnifier-result"
:style="{ width: resultSize + 'px', height: resultSize + 'px', backgroundImage: 'url(' + imageSrc + ')' }"
ref="resultBox"
></div>
</div>
</template>
<script>
import { onMounted, onUnmounted, reactive, ref } from 'vue'
export default {
props: {
imageSrc: {
type: String,
required: true,
},
zoomRatio: {
type: Number,
default: 2,
},
lensSize: {
type: Number,
default: 100,
},
resultSize: {
type: Number,
default: 300,
},
},
setup(props) {
const state = reactive({
zoomed: false,
previewWidth: 0,
previewHeight: 0,
lensWidth: 0,
lensHeight: 0,
resultWidth: 0,
resultHeight: 0,
previewImgTop: 0,
previewImgLeft: 0,
lensTop: 0,
lensLeft: 0,
resultTop: 0,
resultLeft: 0,
previewBox: null,
lensBox: null,
resultBox: null,
previewImg: null,
})
const handleMouseEnter = () => {
state.zoomed = true
}
const handleMouseLeave = () => {
state.zoomed = false
}
const handleMouseMove = (e) => {
const previewRect = state.previewBox.getBoundingClientRect()
const lensRect = state.lensBox.getBoundingClientRect()
// 计算放大镜的位置
state.lensTop = e.clientY - previewRect.top - lensRect.height / 2
state.lensLeft = e.clientX - previewRect.left - lensRect.width / 2
// 防止放大镜越界
if (state.lensTop < 0) {
state.lensTop = 0
}
if (state.lensTop > previewRect.height - lensRect.height) {
state.lensTop = previewRect.height - lensRect.height
}
if (state.lensLeft < 0) {
state.lensLeft = 0
}
if (state.lensLeft > previewRect.width - lensRect.width) {
state.lensLeft = previewRect.width - lensRect.width
}
// 计算放大镜对应的结果的位置
state.resultTop = -(state.lensTop * props.zoomRatio)
state.resultLeft = -(state.lensLeft * props.zoomRatio)
}
onMounted(() => {
// 获取元素
state.previewBox = ref.$refs.previewBox
state.lensBox = ref.$refs.lens
state.resultBox = ref.$refs.resultBox
state.previewImg = ref.$refs.previewImg
// 获取图片的尺寸
const img = new Image()
img.onload = () => {
state.previewWidth = state.previewBox.offsetWidth
state.previewHeight = state.previewBox.offsetHeight
state.lensWidth = state.lensBox.offsetWidth
state.lensHeight = state.lensBox.offsetHeight
state.resultWidth = state.resultBox.offsetWidth
state.resultHeight = state.resultBox.offsetHeight
state.previewImgTop = state.previewImg.offsetTop
state.previewImgLeft = state.previewImg.offsetLeft
}
img.src = props.imageSrc
})
onUnmounted(() => {
// 清除事件监听
state.previewBox.removeEventListener('mouseenter', handleMouseEnter)
state.previewBox.removeEventListener('mouseleave', handleMouseLeave)
state.previewBox.removeEventListener('mousemove', handleMouseMove)
})
return {
...state,
handleMouseEnter,
handleMouseLeave,
handleMouseMove,
}
},
}
</script>
<style scoped>
.magnifier-container {
position: relative;
}
.magnifier-preview {
position: relative;
overflow: hidden;
}
.magnifier-lens {
position: absolute;
cursor: crosshair;
background-repeat: no-repeat;
background-position: 0 0;
opacity: 0.5;
pointer-events: none;
}
.magnifier-result {
position: absolute;
top: 0;
left: 110%;
background-repeat: no-repeat;
background-position: 0 0;
visibility: hidden;
opacity: 0;
transition: opacity 0.3s ease;
}
.magnifier-container:hover .magnifier-lens {
opacity: 0.8;
}
.magnifier-container:hover .magnifier-result {
visibility: visible;
opacity: 1;
}
</style>
```
在上面的代码中,我们使用了 Vue3 的 `setup` 函数来编写这个组件。这个组件包含了三个部分:预览框(`previewBox`)、放大镜(`lens`)和放大结果框(`resultBox`)。
我们使用 `reactive` 函数来创建一个响应式对象 `state`,用于存储组件内部的状态。然后在 `onMounted` 钩子中获取元素和图片的尺寸,并计算出放大镜和放大结果的初始位置。在 `onUnmounted` 钩子中清除事件监听器。
在 `setup` 函数中返回了一些属性和函数,用于在模板中进行绑定和事件监听。在模板中,我们使用 `ref` 来获取元素的引用,然后通过 `v-bind` 和 `:style` 来设置元素的样式和位置。另外,我们使用了 `@mouseenter`、`@mouseleave` 和 `@mousemove` 来监听鼠标的事件,从而实现放大镜的效果。
这个组件可以接收四个参数:
- `imageSrc`:要展示的图片的 URL。
- `zoomRatio`:放大比例,默认为 2。
- `lensSize`:放大镜的大小,默认为 100 像素。
- `resultSize`:放大结果框的大小,默认为 300 像素。
你可以将这个组件导入到你的项目中,然后在需要使用放大镜的地方使用这个组件即可。
阅读全文