• vue项目js实现图片放大镜功能


    效果图:
     
    我写的是vue的组件形式,方便复用,图片的宽高,缩放的比例可以自己定义
    magnifier.vue
    <template>
      <div class="magnify">
      <!-- 左边产品图片区域 -->
        <div class="left_contaner">
          <div class="middle_img" @mouseover="boxMouseOver" @mouseleave="boxMouseLeave">
          <!-- 产品图片 -->
            <img :src="middleImg" alt="">
            <!-- 阴影盒子 -->
            <div class="shade" @mouseover="shadeMouseOver" @mousemove="shadeMouseMove" ref="shade" v-show="isShade"></div>
          </div>
          <!-- 缩略图容器 -->
          <div class="carousel">
          <!-- 左箭头 -->
            <div class="left_arrow arrow" @click="leftArrowClick"></div>
            <!-- 缩略图展示盒子 -->
            <div class="show_box">
              <ul class="picture_container" ref="middlePicture">
                <li class="picture_item" @mouseover="tabPicture(item)" v-for="(item, index) in pictureList" :key="index">
                  <img :src="item.url" class="small_img" alt="">
                </li>
              </ul>
            </div>
            <!-- 向右箭头 -->
            <div class="right_arrow arrow" @click="rightArrowClick"></div>
          </div>
        </div>
        <!-- 右边放大区域 -->
        <div class="right_contanier" v-show="isBig">
          <img :src="middleImg" ref="bigImg" class="big_img" alt="">
        </div>
      </div>
    </template>
    
    <script>
    import $ from 'jquery'
    export default {
      props: {
        middleImgWidth: {
          default: 350,
          type: Number
        }, // 产品图片宽
        middleImgHeight: {
          default: 400,
          type: Number
        }, // 产品图片高
        thumbnailHeight: {
          default: 100,
          type: Number
        }, // 缩略图容器高度
        imgList: Array, // 图片数据
        zoom: {
          default: 2, // 缩略比例,放大比例
          type: Number
        }
      },
      data() {
        return {
          pictureList: [
            {url: 'http://mp.ofweek.com/Upload/News/Img/member645/201711/17170046839337.jpg'},
            {url: 'http://image.buy.ccb.com/merchant/201703/904919627/1522929521661_4.jpg'},
            {url: 'http://image5.suning.cn/uimg/b2c/newcatentries/0070130691-000000000826244625_5_800x800.jpg'},
            {url: 'http://img12.360buyimg.com/n5/s450x450_jfs/t9952/98/2269407420/279171/6137fe2f/59f28b2bN6959e086.jpg'},
            {url: 'http://d.ifengimg.com/w600/p0.ifengimg.com/pmop/2017/1213/A4037864F6728F006B67AAEC51EC8A485F320FD2_size93_w1024_h734.jpeg'},
            {url: 'http://d.ifengimg.com/w600/p0.ifengimg.com/pmop/2017/1213/A4037864F6728F006B67AAEC51EC8A485F320FD2_size93_w1024_h734.jpeg'}
          ],
          middleImg: '', // 中图图片地址
          bigImg: '', // 大图图片地址
          isShade: false, // 控制阴影显示与否
          isBig: false, // 控制放大图显示与否
          initX: 0, // 初始clientX值
          initY: 0, // 初始clientY值
          leftX: 0, // 初始定位left
          topY: 0, // 初始定位top
          middleLeft: 0, // 当前放置小图盒子的定位left值,
          itemWidth: 80, // 缩略图每张的宽度
        }
      },
      created() {
        if (this.imgList && this.imgList.length) {
          this.pictureList = this.imgList
        }
        this.middleImg = this.pictureList[0].url
        // 计算缩略图的宽度,默认是显示4张图片,两边箭头的宽度和为50
        this.itemWidth = (this.middleImgWidth-50) / 4
      },
      mounted() {
        this.$nextTick(() => {
          // 容器的高
          const imgWidth = this.middleImgHeight + this.thumbnailHeight + 20
          // 设置容器宽高
          $('.magnify').css({
             this.middleImgWidth,
            height: imgWidth
          })
          // 设置产品图宽高
          $('.middle_img').css({
             this.middleImgWidth,
            height: this.middleImgHeight
          })
          // 设置移动阴影图宽高
          $('.middle_img .shade').css({
             this.middleImgWidth/this.zoom,
            height: this.middleImgHeight/this.zoom
          })
          // 设置缩略图容器高
          $('.carousel').css({
            height: this.thumbnailHeight
          })
          // 设置每个缩略图宽
          $('.picture_item').css({
             this.itemWidth
          })
          // 设置放大后图片容器的宽高,left
          $('.right_contanier').css({
            left: this.middleImgWidth,
             imgWidth,
            height: imgWidth
          })
          // 设置放大图片的宽高(图片的放大倍数)
          $('.right_contanier .big_img').css({
             imgWidth * this.zoom,
            height: imgWidth * this.zoom
          })
        })
      },
      methods: {
        // 产品图片鼠标移入事件,显示阴影,显示大图
        boxMouseOver (e) {
          console.log(9999, e)
          e.preventDefault();
          e.stopPropagation();
          this.isShade = true
          this.isBig = true
          // 计算阴影的位置
          let x = e.offsetX - $('.shade').width()/2
          let y = e.offsetY - $('.shade').height()/2
          let maxLeft = $('.middle_img').width() - $('.shade').width() 
          let maxTop = $('.middle_img').height() - $('.shade').height()
          x = x <= 0 ? 0 : x
          x = x >= maxLeft ? maxLeft : x
          y = y <= 0 ? 0 : y
          y = y >= maxTop ? maxTop : y
         $('.shade').css({
             left: x,
             top: y
            })
        },
        // 鼠标在阴影移动
        shadeMouseMove (e) {
          e.preventDefault();
          e.stopPropagation();
        //用页面x - 父盒子的offsetLeft - 父盒子的左边框宽度 标红的两个方法补在下面
        var x = this.getEventPage(e).pageX - $('.middle_img')[0].offsetParent.offsetLeft - $('.middle_img')[0].offsetParent.clientLeft;
        //用页面y - 父盒子的offsetTop - 父盒子的上边框宽度
        var y = this.getEventPage(e).pageY - $('.middle_img')[0].offsetParent.offsetTop - $('.middle_img')[0].offsetParent.clientTop;

        //让阴影的坐标居中
        x -= $('.shade').width() / 2;
        y -= $('.shade').height() / 2;

        // 移动边界限制
        let maxLeft = $('.middle_img').width() - $('.shade').width()
        let maxTop = $('.middle_img').height() - $('.shade').height()
        x = x <= 0 ? 0 : x
        x = x >= maxLeft ? maxLeft : x
        y = y <= 0 ? 0 : y
        y = y >= maxTop ? maxTop : y
        // 重新赋值当前的定位值
        $('.shade').css({
          left: x,
          top: y
        })
          // 计算出实时的大图的定位,首先计算出比例
          // 比例为x:大图宽度/小图宽度 y: 大图高度/小图高度,将小图的定位乘以比例就是大图的定位
          const xRate = $('.big_img').width() / $('.middle_img').width()
          const yRate = $('.big_img').height() / $('.middle_img').height()
          $('.big_img').css({
            left: -x*xRate,
            top: -y*yRate
          })
          // console.log(e, x, y, xRate, yRate, 66677)
        },
        // 鼠标移入阴影,去除自定义事件
        shadeMouseOver (e) {
          e.preventDefault();
          e.stopPropagation();
          // console.log(88888, e)
        },
        // 图片移出隐藏阴影和大图
        boxMouseLeave (e) {
          this.isShade = false
          this.isBig = false
        },
        // 切换图片
        tabPicture (item) {
          this.middleImg = item.url
        },
        // 点击左边箭头
        leftArrowClick () {
          if (this.middleLeft < 0) {
            // 每次向右平移一个图片盒子的宽度
            this.middleLeft += this.itemWidth
            $('.picture_container').animate({
              left: this.middleLeft
            }, 500)
          }
        },
        // 点击右边箭头
        rightArrowClick () {
          // 每次向左平移一个盒子的宽度,最多移动的宽度为(图片数组长度-4)*每张缩略图的宽度
          if (this.middleLeft > -this.itemWidth*(this.pictureList.length-4)) {
            this.middleLeft -= this.itemWidth
            $('.picture_container').animate({
              left: this.middleLeft
            }, 500)
          }
          console.log(this.middleLeft)
        }
      }
    }
    </script>
    
    <style scoped>
    .magnify {
      position: relative;
    }
    .left_contaner {
       100%;
      height: 100%;
    }
    .left_contaner .middle_img {
      border: 1px solid #ccc;
      box-sizing: border-box;
      position: relative;
    }
    .left_contaner .shade {
      background-color: rgba(    135,206,235, .5);
      position: absolute;
      top: 0;
      left: 0;
     cursor: move;
    }
    .left_contaner .middle_img img {
       100%;
      height: 100%;
    }
    .left_contaner .carousel {
       100%;
      margin-top: 20px;
      display: -webkit-flex;
    }
    .left_contaner .carousel .show_box {
      flex: 1;
      overflow: hidden;
      position: relative;
    }
    .left_contaner .carousel .arrow {
      flex-basis: 25px;
      cursor: pointer;
    }
    .left_contaner .carousel .left_arrow {
      background: url('http://www.jq22.com/demo/jQuery-fdj201705051102/images/btn_prev.png') no-repeat;
      background-position: center center;
    }
    .left_contaner .carousel .right_arrow {
      background: url('http://www.jq22.com/demo/jQuery-fdj201705051102/images/btn_next.png') no-repeat;
      background-position: center right;
    }
    .left_contaner .carousel .picture_container {
       200%;
      height: 100%;
      position: absolute;
      overflow: hidden;
      top: 0;
      left: 0;
    }
    .left_contaner .picture_container .picture_item {
      height: 100%;
      float: left;
      padding: 5px;
      box-sizing: border-box;
    }
    .left_contaner .picture_container .picture_item:hover {
      border: 2px solid #f2019f;
    }
    .left_contaner .picture_container .picture_item img {
       100%;
      height: 100%;
    }
    .right_contanier {
      overflow: hidden;
      position: absolute;
      top: 0;
      border: 1px solid #ccc;
    }
    .right_contanier .big_img {
      position: absolute;
      top: 0px;
      left: 0px;
    }
    </style>

     之前漏了两个方法,补在下面,放在methods方法里就好了

    /**
         * 获取网页滚出去的距离(包括上面滚出去的部分和左边滚出去的部分)
         * @returns {{scrollTop: (Number|number), scrollLeft: (Number|number)}}
         */
        getPageScroll() {
          return {
            scrollTop: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
            scrollLeft: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0
          }
        },
        /**
        * 获取事件对象点击的点,相对于文档左上角的坐标
        * @param e
        * @returns {{pageX: *, pageY: *}}
        */
        getEventPage(e) {
          return {
            pageX: e.clientX + this.getPageScroll().scrollLeft,
            pageY: e.clientY + this.getPageScroll().scrollTop
          }
        }
    父组件引用
     
    <template>
     <div id="app">
      <img alt="Vue logo" src="./assets/logo.png">
      <!-- 图片放大镜,需要自定义图片的宽高在这里传入,组件有设置默认的宽高,不传也可以 -->
      <magnifier></magnifier>
     </div>
    </template>
    <script>
    // 引入放大镜组件
    import Magnifier from './components/magnifier.vue'
    import $ from 'jquery'
    export default {
    name: 'app',
    components: {
     // 注册
     Magnifier
     }
    }
     
     git-hup地址: https://github.com/shengbid/vue-demo  这个文件是平时练习的项目,里面还有一些我写的其他博客的源码,有需要可以下载看看
  • 相关阅读:
    SpringBoot项目启动与关闭脚本
    springboot mybatis启动初始化数据库
    springboot mybatis多数据库支持
    Tomcat配置https访问
    Oracle批量生成版本
    Oracle创建用户表空间
    OracleServiceXE服务没有了
    IDEA离线升级
    js过滤并校验XSS
    docker命令
  • 原文地址:https://www.cnblogs.com/steamed-twisted-roll/p/11359625.html
Copyright © 2020-2023  润新知