美文网首页
vue封装图片放大镜效果

vue封装图片放大镜效果

作者: zkzhengmeng | 来源:发表于2023-10-31 09:25 被阅读0次

1.新建Imgzoom组件代码如下:

<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" v-if="prevShow"><i class="el-icon-caret-left"></i></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" v-if="prevShow"> <i class="el-icon-caret-right"></i> </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,
        prevShow:false,
      }
    },
    created() {
      if (this.imgList.length > 0) {
        this.bigImgSrc = this.imgList[0].b;
        this.smallImgSrc = this.imgList[0].s;
      }
      this.prevShow = this.imgList.length >4?true:false;
    },
    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">
  *{
    padding: 0;
    margin: 0;
  }
  .container {
    margin: 5px 0 15px;
    overflow: hidden;

    #goodsZoom {
      width: 500px;
      #zoomTop {
        width: 500px;
        position: relative;
        #smallPic {
          width: 500px;
          height: 350px;
          border: 1px solid #dfdfdf;
          position: relative;
          img {
            width: 100%;
            height: 100%;
          }
          #mask {
            width: 200px;
            height: 200px;
            background: rgba(255, 255, 255, .5);
            border: 1px solid #ddd;
            position: absolute;
            left: 0px;
            top: -1px;
          }
        }

        #bigPic {
          margin-left: 90px;
          width: 500px;
          height: 350px;
          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: 500px;
        margin-top: 5px;
        a {
          width: 20px;
          height: 20px;
          background: #409eff;
          text-align: center;
          line-height: 20px;
          border-radius: 50px;
          float: left;
          text-decoration: none;
          color:#ffffff;
          &:first-child {
            margin-right: 4px;
            margin-top: 18px;
          }
          .el-icon-caret-left{
            margin: 2px 2px 2px 0;
          }
        }
        .next{
          margin-top: 18px;
          .el-icon-caret-right{
            margin:2px;
          }
        }
        #picList {
          width: 455px;
          height: 56px;
          float: left;
          overflow: hidden;
          position: relative;

          ul {
            white-space: nowrap;
            font-size: 0px;
            position: absolute;
            left: 0px;
            transition: 0.5s;
            li {
              width: 80px;
              height: 50px;
              padding: 2px;
              margin-right: 10px;
              display: inline-block;
              cursor: pointer;
              img {
                width: 80px;
                height: 50px;
              }
            }
          }
        }
      }
    }
  }
</style>

2.在页面中使用

<template>
  <div class="dashboard-container">
        <ImgZoom :imgList="imgList" />
  </div>
</template>

<script>
import ImgZoom from '@/components/imgZoom'
export default {
  name: 'Dashboard',
  components: {
    ImgZoom
  },
  data() {
    return {
      imgList: [
        {b: require('@/assets/ban-01.png'), s: require('@/assets/ban-01.png')},
        {b: require('@/assets/ban-02.png'), s: require('@/assets/ban-02.png')},
        {b: require('@/assets/ban-03.png'), s: require('@/assets/ban-03.png')},
        {b: require('@/assets/ban-04.png'), s: require('@/assets/ban-04.png')}
      ]
    }
  }
}
</script>

<style lang="scss"  scoped>
</style>

相关文章

网友评论

      本文标题:vue封装图片放大镜效果

      本文链接:https://www.haomeiwen.com/subject/olpiidtx.html