vue实战——商品放大镜组件封装及效果实现

Posted 北溟溟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue实战——商品放大镜组件封装及效果实现相关的知识,希望对你有一定的参考价值。

前言

本节内容以vue为基础,实现一个商品放大镜组件的封装,及动画效果实现,通过本节内容,我们也可以实现其它h5相关的功能需求。商品放大镜功能在实际开发中还是有广泛需求的,尤其在商城项目中,为了更好的使用该功能,作者将该商品放大镜功能封装为一个组件,便于使用和维护。效果如下:

正文

  • 创建一个商品放大镜的组件goods-magnifier-zoom.vue

  •  封装商品放大镜组件

说明:

①通过注册鼠标的移入、移出、移动事件,实现商品放大镜的效果

<div id="smallPic" @mouseover="handlerMouseOver" @mouseleave="handlerMouseLeave"
             @mousemove="handlerMouseMove">

 

②通过父子组件实现图片数据的传递

props: 
    imgList: 
      type: Array,
      required: true,
      default: [],
    ,
  ,

③使用scss实现样式布局设置

<style scoped lang="scss">

④完整组件封装实现 

<template>
  <div class="container">
    <div id="goodsZoom">
      <div id="zoomTop">
        <!--        小图框-->
        <div id="smallPic" @mouseover="handlerMouseOver" @mouseleave="handlerMouseLeave"
             @mousemove="handlerMouseMove">
          <img :src="smallImgSrc">
          <!--          蒙版元素-->
          <div id="mask" v-show="show"></div>
        </div>
        <!--        大图框-->
        <div id="bigPic" v-show="show">
          <img :src="bigImgSrc" id="bigImg">
        </div>
      </div>
      <div id="zoomBottom">
        <a href="javascript:;" class="prev" @click="handlerPrev"> < </a>
        <div id="picList">
          <ul>
            <li v-for="(item,index) in imgList" @click="thumbnailClick(item)">
              <img :src="item.s">
            </li>
          </ul>
        </div>
        <a href="javascript:;" class="next" @click="handlerNext"> > </a>
      </div>
    </div>
  </div>
</template>

<script>
export default 
  name: "goods-magnifier-zoom",
  props: 
    imgList: 
      type: Array,
      required: true,
      default: [],
    ,
  ,
  data() 
    return 
      show: false,//是否显示
      bigImgSrc: '',
      smallImgSrc: '',
      start: 0,
    
  ,
  created() 
    if (this.imgList.length > 0) 
      this.bigImgSrc = this.imgList[0].b;
      this.smallImgSrc = this.imgList[0].s;
    

  ,
  methods: 
    //鼠标移入事件
    handlerMouseOver() 
      this.show = true;
    ,
    //鼠标移出事件
    handlerMouseLeave() 
      this.show = false;
    ,
    //鼠标移动事件
    handlerMouseMove(data) 
      const smallPic = document.getElementById("smallPic");
      const bigPic = document.getElementById("bigPic");
      const bigImg = document.getElementById("bigImg");
      const zoomTop = document.getElementById("zoomTop");
      const mask = document.getElementById("mask");
      //蒙版边界设置
      let left = data.clientX - smallPic.getBoundingClientRect().left - mask.offsetWidth / 2;
      let top = data.clientY - smallPic.getBoundingClientRect().top - mask.offsetHeight / 2;
      //边界判断
      if (left < 0) 
        left = 0;
       else if (left > smallPic.clientWidth - mask.offsetWidth) 
        left = smallPic.clientWidth - mask.offsetWidth;
      
      if (top < -1) 
        top = -1;
       else if (top > smallPic.clientHeight - mask.offsetHeight) 
        top = smallPic.clientHeight - mask.offsetHeight;
      
      mask.style.left = left + "px";
      mask.style.top = top + "px";
      let scale = (smallPic.clientWidth - mask.offsetWidth) / (bigImg.offsetWidth - bigPic.clientWidth);
      console.log(scale);
      bigImg.style.left = -left / scale + "px";
      bigImg.style.top = -top / scale + "px";
    ,
    //缩略图点击效果
    thumbnailClick(data) 
      this.bigImgSrc = data.b;
      this.smallImgSrc = data.s;
    ,
    //点击前一个
    handlerPrev() 
      let ul = document.querySelector('#goodsZoom #zoomBottom #picList ul');
      let liNodes = document.querySelectorAll('#goodsZoom #zoomBottom #picList li');
      if (liNodes.length === 0) 
        return;
      
      //步长
      let step = (liNodes[0].offsetWidth + 20) * 2;
      this.start -= step;
      if (this.start < 0) 
        this.start = 0;
      
      ul.style.left = -this.start + "px";
    ,
    //点击下一个
    handlerNext() 
      let ul = document.querySelector('#goodsZoom #zoomBottom #picList ul');
      let liNodes = document.querySelectorAll('#goodsZoom #zoomBottom #picList li');
      if (liNodes.length === 0) 
        return;
      
      //步长
      let step = (liNodes[0].offsetWidth + 20) * 2;
      //总体运动的距离值 = ul的宽度 - div框的宽度 = (图片的总数 - div中显示的数量) * (li的宽度 + 20)
      let endPosition = (liNodes.length - 5) * (liNodes[0].offsetWidth + 20);
      this.start += step;
      if (this.start > endPosition) 
        this.start = endPosition;
      
      ul.style.left = -this.start + "px";
    ,
  ,
;
</script>

<style scoped lang="scss">
.container 
  margin: 5px 0 15px;
  overflow: hidden;

  #goodsZoom 
    #zoomTop 
      width: 400px;
      position: relative;

      #smallPic 
        width: 400px;
        height: 400px;
        border: 1px solid #dfdfdf;
        position: relative;

        img 

        

        #mask 
          width: 200px;
          height: 200px;
          background: rgba(255, 255, 255, .5);
          border: 1px solid #ddd;
          position: absolute;
          left: 0px;
          top: -1px;
        
      

      #bigPic 
        width: 400px;
        height: 400px;
        border: 1px solid #ddd;
        left: 420px;
        top: 0px;
        position: absolute;
        overflow: hidden;

        #bigImg 
          width: 800px;
          height: 800px;
          position: absolute;
          left: 0px;
          top: 0px;
        
      
    

    #zoomBottom 
      width: 400px;
      margin-top: 5px;

      a 
        width: 10px;
        height: 54px;
        border: 1px solid #ccc;
        background: #ebebeb;
        text-align: center;
        line-height: 54px;
        float: left;
        text-decoration: none;

        &:first-child 
          margin-right: 4px;
        
      

      #picList 
        width: 372px;
        height: 56px;
        float: left;
        overflow: hidden;
        position: relative;

        ul 
          white-space: nowrap;
          font-size: 0px;
          position: absolute;
          left: 0px;
          transition: 0.5s;

          li 
            width: 50px;
            height: 50px;
            border: 1px solid #ccc;
            padding: 2px;
            margin-right: 20px;
            display: inline-block;

            img 
              width: 50px;
              height: 50px;
            
          
        
      
    
  

</style>
  • 创建一个测试页面GoodsZoom.vue,使用components引入组件 

①引入组件

import goodsMagnifierZoom from '@/components/goods-magnifier-zoom.vue';

export default 
  name: "GoodsZoom",
  components: 
    goodsMagnifierZoom: goodsMagnifierZoom,
  

 

②使用组件

<goods-magnifier-zoom :imgList="imgList"></goods-magnifier-zoom>

③完整代码实现

<template>
  <div class="container">
    <div class="title">
      <span>商品放大镜</span>
      <el-divider direction="vertical"></el-divider>
      <router-link to="home">
        <span style="font-size: 18px;">退出</span>
      </router-link>
    </div>
    <el-divider>Test Staring</el-divider>
    <goods-magnifier-zoom :imgList="imgList"></goods-magnifier-zoom>
  </div>
</template>

<script>
import goodsMagnifierZoom from '@/components/goods-magnifier-zoom.vue';

export default 
  name: "GoodsZoom",
  data() 
    return 
      imgList: [
        b: require('@/assets/nav/b1.png'), s: require('@/assets/nav/s1.png'),
        b: require('@/assets/nav/b2.png'), s: require('@/assets/nav/s2.png'),
        b: require('@/assets/nav/b3.png'), s: require('@/assets/nav/s3.png'),
        b: require('@/assets/nav/b1.png'), s: require('@/assets/nav/s1.png'),
        b: require('@/assets/nav/b2.png'), s: require('@/assets/nav/s2.png'),
        b: require('@/assets/nav/b3.png'), s: require('@/assets/nav/s3.png'),
        b: require('@/assets/nav/b1.png'), s: require('@/assets/nav/s1.png'),
        b: require('@/assets/nav/b2.png'), s: require('@/assets/nav/s2.png'),
        b: require('@/assets/nav/b3.png'), s: require('@/assets/nav/s3.png'),
        b: require('@/assets/nav/b1.png'), s: require('@/assets/nav/s1.png'),
        b: require('@/assets/nav/b2.png'), s: require('@/assets/nav/s2.png'),
        b: require('@/assets/nav/b3.png'), s: require('@/assets/nav/s3.png'),
        b: require('@/assets/nav/b1.png'), s: require('@/assets/nav/s1.png'),
        b: require('@/assets/nav/b2.png'), s: require('@/assets/nav/s2.png'),
        b: require('@/assets/nav/b3.png'), s: require('@/assets/nav/s3.png')
      ],
    
  ,
  components: 
    goodsMagnifierZoom: goodsMagnifierZoom,
  

</script>

<style scoped lang="scss">
.container 
  padding: 10px;
  overflow: hidden;

  .title 
    font-size: 20px;
    font-weight: bold;
  


</style>

  • 启动项目 
  • 访问页面测试组件效果

①默认效果

 ②鼠标移入效果

③鼠标移动效果

④点击缩略图,切换商品

⑤切换缩略图

结语

至此,关于本节内容到这里就结束了,我们下期见。。。记得点赞、关注、收藏,你的支持就是我最大的创作动力。

以上是关于vue实战——商品放大镜组件封装及效果实现的主要内容,如果未能解决你的问题,请参考以下文章

vue3.0中手写商品放大镜效果

Vue实现商品放大镜效果

VUE项目实战38实现商品分类的树形表格

VUE项目实战50商品列表分页查询和删除效果

VUE项目实战40添加商品分类功能

Vue3返回顶部组件及返回顶部js封装