您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax |

vue3封装放大镜组件的实例代码

51自学网 2022-05-02 21:30:48
  javascript

组件基础结构

结尾有完整代码可直接复制使用

目的:封装图片预览组件,实现鼠标悬停切换效果

落地代码:

<template>  <div class="goods-image">    <div class="middle">      <img :src="images[currIndex]" alt="">    </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 } from 'vue'export default {  name: 'GoodsImage',  props: {    images: {      type: Array,      default: () => []    }  },  setup (props) {    const currIndex = ref(0)    return { currIndex }  }}</script><style scoped lang="less">.goods-image {  width: 480px;  height: 400px;  position: relative;  display: flex;  .middle {    width: 400px;    height: 400px;    background: #f5f5f5;  }  .small {    width: 80px;    li {      width: 68px;      height: 68px;      margin-left: 12px;      margin-bottom: 15px;      cursor: pointer;      &:hover,&.active {        border: 2px solid @xtxColor;      }    }  }}</style>

图片放大镜

目的:实现图片放大镜功能

步骤:

  • 首先准备大图容器和遮罩容器
  • 然后使用@vueuse/core的useMouseInElement方法获取基于元素的偏移量
  • 计算出 遮罩容器定位与大容器背景定位  暴露出数据给模板使用

落地代码:

<template>  <div class="goods-image">+     // 实现右侧大图布局效果(背景图放大4倍)+    <div class="large" :style="[{backgroundImage:`url(${images[currIndex]})`}]"></div>    <div class="middle">      <img :src="images[currIndex]" alt="">+      // 准备待移动的遮罩容器+     <div class="layer"></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 } from 'vue'export default {  name: 'GoodsImage',  props: {    images: {      type: Array,      default: () => []    }  },  setup (props) {    const currIndex = ref(0)    return { currIndex }  }}</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;    background: #f5f5f5;+    position: relative;+    cursor: move;+    // 遮罩样式+    .layer {+      width: 200px;+      height: 200px;+      background: rgba(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: 2px solid @xtxColor;      }    }  }}</style>

安装vueuse

npm i @vueuse/core@5.3.0

目前5.3.0版本相对稳定

vueuse提供的监听进入指定范围方法的基本使用

import { useMouseInElement } from '@vueuse/core'const { elementX, elementY, isOutside } = useMouseInElement(target)

方法的参数target表示被监听的DOM对象;返回值elementX, elementY表示被监听的DOM的左上角的位置信息left和top;isOutside表示是否在DOM的范围内,true表示在范围之外。false表示范围内。

功能实现

<div v-if="isShow" class="large" :style="[{ backgroundImage: `url(${images[currIndex]})` }, bgPosition]"></div><div class="middle" ref="target">   <img :src="images[currIndex]" alt="" />   <div class="layer" v-if="isShow" :style="[position]"></div></div>setup () {// 被监听的区域const target = ref(null)// 控制遮罩层和预览图的显示和隐藏const isShow = ref(false)// 定义遮罩的坐标const position = reactive({      left: 0,      top: 0})// 右侧预览大图的坐标const bgPosition = reactive({      backgroundPositionX: 0,      backgroundPositionY: 0})return { position, bgPosition, target, isShow }}
const { elementX, elementY, isOutside } = useMouseInElement(target)  // 基于侦听器侦听值的变化  watch([elementX, elementY, isOutside], () => {    // 通过标志位控制显示和隐藏    isShow.value = !isOutside.value    if (isOutside.value) return    // X方向坐标范围控制    if (elementX.value < 100) {      // 左侧      position.left = 0    } else if (elementX.value > 300) {      // 右侧      position.left = 200    } else {      // 中间      position.left = elementX.value - 100    }    // Y方向坐标范围控制    if (elementY.value < 100) {      position.top = 0    } else if (elementY.value > 300) {      position.top = 200    } else {      position.top = elementY.value - 100    }    // 计算预览大图的移动的距离    bgPosition.backgroundPositionX = -position.left * 2 + 'px'    bgPosition.backgroundPositionY = -position.top * 2 + 'px'    // 计算遮罩层的位置    position.left = position.left + 'px'    position.top = position.top + 'px'  })

完整代码

<template>  <div class="goods-image">    <div v-if="isShow" class="large" :style="[{ backgroundImage: `url(${images[currIndex]})` }, bgPosition]"></div>    <div class="middle" ref="target">      <img :src="images[currIndex]" alt="" />      <div class="layer" v-if="isShow" :style="[position]"></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: 'GoodsImage',  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      }      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 {  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;    background: #f5f5f5;     position: relative;    cursor: move;    .layer {      width: 200px;      height: 200px;      background: rgba(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: 2px solid @xtxColor;      }    }  }}</style>

总结

到此这篇关于vue3封装放大镜组件的文章就介绍到这了,更多相关vue3封装放大镜组件内容请搜索wanshiok.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持wanshiok.com!


如何利用vue3实现放大镜效果实例详解
webpack搭建脚手架打包TypeScript代码
51自学网,即我要自学网,自学EXCEL、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。
京ICP备13026421号-1