当前位置 博文首页 > 文章内容

    如何利用vue3实现放大镜效果实例详解

    作者:shunshunshun18 栏目:未分类 时间:2021-09-20 14:44:05

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    前言

    逛购物网站的时候,想必大家都见过鼠标放到商品上,会有一个放大的效果。今天我们就自己动手封装一个放大镜效果的全局组件,一起来看下吧~

    一、封装的意义

    • 从技术角度
      • 通过vue插件方式封装为全局组件,整个项目其他位置也可以使用,且使用方便
      • 模块化开发思想,一个模块实现一个功能
    • 用户角度
      • 可以带来更好的浏览体验
      • 可以看到商品的细节

    二、如何封装?

    1.  准备

    需要用到@vueuse/core的useMouseInElement方法,所以先在项目根目录下打开终端执行如下命令

    这里安装的指定版本的,各位小伙伴儿按需选择

    npm install @vueuse/core@5.3.0
    

    2.  开始封装

    还是像之前的文章一样,使用vue插件的方式注册全局组件

    在src/components下存放封装的全局组件,这个目录下新建enlarge-images.vue文件。

    代码如下(示例):

    <template>
      <div class="goods-image">
        <!-- 预览大图 -->
        <div class="large" :style='[{backgroundImage: `url(${images[currIndex]})`}, bgPosition]' v-show='isShow'></div>
        <div class="middle" ref='target'>
          <!-- 左侧的大图 -->
          <img :src="images[currIndex]" alt="">
          <!-- 遮罩层 -->
          <div class="layer" :style='[position]' v-show='isShow'></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: 'EnlargeImages',
      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
          }
          // console.log(elementX.value, elementY.value, isOutside.value)
          // 计算预览大图背景的位置
          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 {
      box-sizing: border-box;
      width: 480px;
      height: 400px;
      position: relative;
      display: flex;
      z-index: 500;
       img {
            width: 100%;
            height: 100%;
        }
      .large {
        position: absolute;
        top: 0;
        left: 410px;
        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, 0.2);
          left: 0;
          top: 0;
          position: absolute;
        }
      }
      .small {
        margin: 0;
        padding: 0;
        width: 80px;
        li {
          width: 68px;
          height: 68px;
          margin: 10px;
          list-style: none;
          cursor: pointer;
          &:hover,
          &.active {
            border: 2px solid #27ba9b;
          }
        }
      }
    }
    </style>
    
    

    src/components下新建index.js

    import EnlargeImages from './enlarge-images.vue'
    
    export default {
      install (app) {
        app.component(EnlargeImages.name, EnlargeImages)
      }
    }
    

    main.js中注册为插件

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    // 自己封装的
    import myUI from './components'
    
    createApp(App).use(store).use(router).use(myUI).mount('#app')
    
    

    3. 使用

    这里借助固定的数据进行测试

    代码如下(示例):

    <template>
      <div class="home-banner">
        <!-- 放大镜效果 -->
        <enlarge-images :images="images"/>
      </div>
    </template>
    
    <script>
    
    export default {
      name: 'App',
      setup() {
        const images = [
          'http://blog.iis7.com/">vue常用工具函数这篇文章。