使用vue3的setup写法,在不使用插件和其他库的情况下,写一个好用的电商放大镜组件,放大镜可以自己传入放大的比例和大小

时间: 2023-07-16 20:16:31 浏览: 48
好的,下面是一个简单的电商放大镜组件的实现: ```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 像素。 你可以将这个组件导入到你的项目中,然后在需要使用放大镜的地方使用这个组件即可。

相关推荐

最新推荐

recommend-type

使用Vue组件实现一个简单弹窗效果

主要介绍了使用Vue组件实现一个简单弹窗效果,本文主要内容会涉及到弹窗遮罩的实现, slot 插槽的使用方式,props 、 $emit 传参,具体组件代码也传上去了。需要的朋友可以参考下
recommend-type

基于vue写一个全局Message组件的实现

主要介绍了基于vue写一个全局Message组件的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
recommend-type

使用Vue自定义数字键盘组件(体验度极好)

最近做 Vue 开发,因为有不少页面涉及到金额输入,产品老是觉得用原生的 input 进行金额输入的话 体验很不好,于是自己动手写了一个使用Vue自定义数字键盘组件,具体实现代码大家参考下本
recommend-type

使用form-create动态生成vue自定义组件和嵌套表单组件

主要介绍了使用form-create动态生成vue自定义组件和嵌套表单组件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
recommend-type

vue组件中使用iframe元素的示例代码

本篇文章主要介绍了vue组件中使用iframe元素的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

实现实时数据湖架构:Kafka与Hive集成

![实现实时数据湖架构:Kafka与Hive集成](https://img-blog.csdnimg.cn/img_convert/10eb2e6972b3b6086286fc64c0b3ee41.jpeg) # 1. 实时数据湖架构概述** 实时数据湖是一种现代数据管理架构,它允许企业以低延迟的方式收集、存储和处理大量数据。与传统数据仓库不同,实时数据湖不依赖于预先定义的模式,而是采用灵活的架构,可以处理各种数据类型和格式。这种架构为企业提供了以下优势: - **实时洞察:**实时数据湖允许企业访问最新的数据,从而做出更明智的决策。 - **数据民主化:**实时数据湖使各种利益相关者都可
recommend-type

解释minorization-maximization (MM) algorithm,并给出matlab代码编写的例子

Minorization-maximization (MM) algorithm是一种常用的优化算法,用于求解非凸问题或含有约束的优化问题。该算法的基本思想是通过构造一个凸下界函数来逼近原问题,然后通过求解凸下界函数的最优解来逼近原问题的最优解。具体步骤如下: 1. 初始化参数 $\theta_0$,设 $k=0$; 2. 构造一个凸下界函数 $Q(\theta|\theta_k)$,使其满足 $Q(\theta_k|\theta_k)=f(\theta_k)$; 3. 求解 $Q(\theta|\theta_k)$ 的最优值 $\theta_{k+1}=\arg\min_\theta Q(
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。