zoom1.vue

<template>
  <div id="zoomBox" :style="getStyleStr">
    <div id="small-box">
      <div id="float-box"></div>
      <img :style="getStyleStr" :src="minImgUrl" />
    </div>
    <div id="big-box" :style="getStyleStr">
      <img class="maxImg" :style="`width: ${boxWidth}px`" :src="maxImgUrl" />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      objZoomBox: null,
      objSmallBox: null,
      objFloatBox: null,
      objBigBox: null,
      objBigBoxImg: null,
      nowSacle: null,
    };
  },
  props: {
    // 缩放比列
    sacle: {
      type: Number,
      default: 1.5,
    },
    // 最大缩放比例
    maxSacle: {
      type: Number,
      default: 3,
    },
    // 最小缩放比例
    minSacle: {
      type: Number,
      default: 1,
    },
    // 盒子宽
    boxWidth: {
      type: Number,
      default: 343,
    },
    // 盒子高
    boxHeight: {
      type: Number,
      default: 430,
    },
    // 图片地址
    minImgUrl: {
      type: String,
      default:
        'https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
    },
    // 图片地址
    maxImgUrl: {
      type: String,
      default:
        'https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
    },
  },
  computed: {
    getStyleStr() {
      return `width: ${this.boxWidth}px; height: ${this.boxHeight}px`;
    },
  },
  mounted() {
    this.nowSacle = this.sacle;
    //找五个个元素:demo,smallBox,foatBox,bigfloatBox,imgs,
    const objZoomBox = document.getElementById('zoomBox');
    const objSmallBox = document.getElementById('small-box');
    const objFloatBox = document.getElementById('float-box');
    const objBigBox = document.getElementById('big-box');
    const objBigBoxImg = document.querySelector('.maxImg');
    const _this = this;
    this.objZoomBox = objZoomBox;
    this.objSmallBox = objSmallBox;
    this.objFloatBox = objFloatBox;
    this.objBigBox = objBigBox;
    this.objBigBoxImg = objBigBoxImg;
    //给小盒子添加事件,移入和移出
    //移入:浮动的box和和bigBox显示
    objZoomBox.onmouseover = function () {
      objFloatBox.style.display = 'block';
      objBigBox.style.display = 'block';
      _this.changeImgWidth();
    };
    //移除:浮动的box和bigBox隐藏
    objZoomBox.onmouseout = function () {
      objFloatBox.style.display = 'none';
      objBigBox.style.display = 'none';
      objBigBoxImg.style.width = objZoomBox.clientWidth + 'px';
      _this.changeImgWidth(true);
    };

    // 鼠标滑动事件
    objZoomBox.onmousewheel = function (event) {
      if (event.deltaY < 0) {
        _this.nowSacle += 0.05;
      } else {
        _this.nowSacle -= 0.05;
      }
      if (_this.nowSacle < _this.minSacle) {
        _this.nowSacle = _this.minSacle;
      }
      if (_this.nowSacle > _this.maxSacle) {
        _this.nowSacle = _this.maxSacle;
      }
      _this.changeImgWidth();
      event.preventDefault();
    };

    //给小盒子添加鼠标移动事件
    objZoomBox.onmousemove = function (ev) {
      _this.setSize(ev);
    };
  },
  methods: {
    // 改变放大图片的大小
    changeImgWidth(notRender) {
      const { objZoomBox, objBigBoxImg, nowSacle } = this;
      if (!notRender) {
        const demoWidth = objZoomBox.clientWidth;
        objBigBoxImg.style.width = demoWidth * nowSacle + 'px';
        this.setSize(event);
      }
    },
    // 设置放大图片数据
    setSize(ev) {
      const { objZoomBox, objSmallBox, objFloatBox, objBigBox, objBigBoxImg } = this;
      const _event = ev || window.event; //做兼容性,兼容IE
      //1计算当前坐标值 = 鼠标距离屏幕左边的距离 - 当前盒子距离距离屏幕左边的距离 - 浮动盒子的一半
      const zoomBoxLeft = objZoomBox.getBoundingClientRect().left;
      const zoomBoxTop = objZoomBox.getBoundingClientRect().top;
      let left = _event.clientX - zoomBoxLeft - objFloatBox.offsetWidth / 2;
      let top = _event.clientY - zoomBoxTop - objFloatBox.offsetHeight / 2;

      //5.优化,在前面加判断,不让其溢出,加判断
      if (left < 0) left = 0;
      if (top < 0) top = 0;
      if (left > objSmallBox.offsetWidth - objFloatBox.offsetWidth) {
        left = objSmallBox.offsetWidth - objFloatBox.offsetWidth;
      }
      if (top > objSmallBox.offsetHeight - objFloatBox.offsetHeight)
        top = objSmallBox.offsetHeight - objFloatBox.offsetHeight;

      //2把值赋值给放大镜
      objFloatBox.style.left = left + 'px';
      objFloatBox.style.top = top + 'px';

      //3计算比例
      const percentX = left / (objSmallBox.offsetWidth - objFloatBox.offsetWidth);
      const percentY = top / (objSmallBox.offsetHeight - objFloatBox.offsetHeight);

      //4利用这个比例计算距离后赋值给右侧的图片
      objBigBoxImg.style.left = -percentX * (objBigBoxImg.offsetWidth - objBigBox.offsetWidth) + 'px';
      objBigBoxImg.style.top = -percentY * (objBigBoxImg.offsetHeight - objBigBox.offsetHeight) + 'px';
    },
  },
};
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
#zoomBox {
  display: block;
  margin: 5px;
  position: relative;
  border: 1px solid #ccc;
}
#small-box {
  position: relative;
  z-index: 1;
}
/* #small-box img {
  width: 343px;
  height: 430px;
} */
#float-box {
  display: none;
  width: 160px;
  height: 120px;
  position: absolute;
  background: #ffffcc;
  border: 1px solid #ccc;
  filter: alpha(opacity=50);
  opacity: 0.5;
}
#big-box {
  display: none;
  position: absolute;
  top: 0;
  left: 0px;
  /* width: 343px;
  height: 430px; */
  overflow: hidden;
  border: 1px solid #ccc;
  z-index: 10;
  cursor: crosshair;
}
#big-box img {
  display: inline-block;
  /* width: 343px; */
  position: absolute;
  z-index: 5;
  max-width: inherit;
}
</style>

zoom2.vue

<template>
  <div id="moveBox" :style="`width: ${boxWidth}px`">
    <div id="mirror">
      <img :src="maxImgUrl" class="maxImg2" />
    </div>
    <div id="pic">
      <img :style="`width: ${boxWidth}px`" :src="minImgUrl" class="nowImg" />
    </div>
  </div>
</template>

<script>
export default {
  props: {
    boxWidth: {
      type: Number,
      default: 323,
    },
    sacle: {
      type: Number,
      default: 3,
    },
    // 最大缩放比例
    maxSacle: {
      type: Number,
      default: 3,
    },
    // 最小缩放比例
    minSacle: {
      type: Number,
      default: 1,
    },
    // 图片地址
    minImgUrl: {
      type: String,
      default:
        'https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
    },
    // 图片地址
    maxImgUrl: {
      type: String,
      default:
        'https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg',
    },
  },
  data() {
    return {
      nowSacle: null,
      mirror: null,
      moveBox: null,
      nowImg: null,
      maxImg2: null,
    };
  },
  mounted() {
    this.nowSacle = this.sacle;
    this.$nextTick(() => {
      const mirror = document.querySelector('#mirror');
      const moveBox = document.querySelector('#moveBox');
      const nowImg = document.querySelector('.nowImg');
      const maxImg2 = document.querySelector('.maxImg2');
      const _this = this;

      this.mirror = mirror;
      this.moveBox = moveBox;
      this.nowImg = nowImg;
      this.maxImg2 = maxImg2;

      moveBox.onmousemove = function (e) {
        const ev = e ? e : window.event;
        mirror.style.display = 'block';
        _this.moving(ev);
      };
      moveBox.onmouseout = function () {
        mirror.style.display = 'none';
      };
      moveBox.onmouseover = function () {
        mirror.style.display = 'block';
      };
      maxImg2.onmousewheel = function (event) {
        if (event.deltaY < 0) {
          _this.nowSacle += 0.05;
        } else {
          _this.nowSacle -= 0.05;
        }
        if (_this.nowSacle < _this.minSacle) {
          _this.nowSacle = _this.minSacle;
        }
        if (_this.nowSacle > _this.maxSacle) {
          _this.nowSacle = _this.maxSacle;
        }
        _this.moving(event);
        // 放大图片宽度
        event.preventDefault();
      };
    });
  },
  methods: {
    moving(e) {
      const { mirror, nowImg, maxImg2, nowSacle } = this;
      const nowImgLeft = nowImg.getBoundingClientRect().left;
      const nowImgTop = nowImg.getBoundingClientRect().top;
      const mirrorWidth = mirror.offsetWidth;
      const mirrorHeight = mirror.offsetHeight;
      const nowImgWidth = nowImg.offsetWidth;
      const nowImgHeight = mirror.offsetHeight;
      const picWidth = document.querySelector('.nowImg').offsetWidth;
      const picHeight = document.querySelector('.nowImg').offsetHeight;
      // 鼠标距离
      const x = e.clientX - nowImgLeft;
      const y = e.clientY - nowImgTop;
      const _this = this;

      /**(当前x位置 - 放大镜盒子一半) / 当前图片宽度 <这一步操作得到位置与盒子宽度的比例>
       * 用刚才得到的比例 * (当前图片的宽度 * 缩放比例) <得到放大后的盒子的大概位置>
       * 因为放大镜也有宽度,用刚才得到的值 + 放大镜的一半 * (放大倍数 - 1) <得到最后放大图片的准确x位置,y位置同理>
       */
      const maxImgX =
        ((x - mirrorWidth / 2) / nowImgWidth) * nowImgWidth * nowSacle + (mirrorWidth / 2) * (nowSacle - 1);
      const maxImgY =
        ((y - mirrorHeight / 2) / nowImgHeight) * nowImgHeight * nowSacle + (mirrorHeight / 2) * (nowSacle - 1);

      // 放大图片宽度
      maxImg2.style.width = nowImg.clientWidth * nowSacle + 'px';
      if (Math.floor(x) === nowImgWidth || Math.floor(x) <= 0) {
        mirror.style.display = 'none';
      }

      // 左边缘限制
      if (x - mirrorWidth / 2 < 0 && y - mirrorHeight / 2 > 0 && y + mirrorHeight / 2 < picHeight) {
        mirror.style.left = 0 + 'px';
        maxImg2.style.top = -maxImgY + 'px';
        mirror.style.top = y - mirrorHeight / 2 + 'px';
      }
      // 上边缘限制
      if (y - mirrorHeight / 2 < 0 && x - mirrorWidth / 2 > 0 && x + mirrorWidth / 2 < picWidth) {
        mirror.style.top = 0 + 'px';
        maxImg2.style.left = -maxImgX + 'px';
        mirror.style.left = x - mirrorWidth / 2 + 'px';
        if (x - mirrorWidth / 2 < 0) {
          mirror.style.left = 0 + 'px';
        }
      }
      // 右边缘限制
      if (x + mirrorWidth / 2 > picWidth && y + mirrorHeight / 2 < picHeight && y - mirrorHeight / 2 > 0) {
        mirror.style.left = picWidth - mirrorWidth + 'px';
        maxImg2.style.top = -maxImgY + 'px';
        mirror.style.top = y - mirrorHeight / 2 + 'px';
      }
      // 下边缘限制
      if (y + mirrorHeight / 2 > picHeight && x + mirrorWidth / 2 < picWidth && x - mirrorWidth / 2 > 0) {
        mirror.style.top = picHeight - mirrorHeight + 'px';
        maxImg2.style.left = -maxImgX + 'px';
        mirror.style.left = x - mirrorWidth / 2 + 'px';
      }

      if (x <= picWidth && y <= picHeight && x >= -picWidth && y >= -picHeight) {
        _this.changePosition(x, y);
      }
    },
    changePosition(x, y) {
      const { mirror, nowImg, maxImg2, nowSacle } = this;
      // 放大镜宽
      const mirrorWidth = mirror.offsetWidth;
      // 放大镜高
      const mirrorHeight = mirror.offsetHeight;
      const nowImgWidth = nowImg.offsetWidth;
      const nowImgHeight = mirror.offsetHeight;
      const picWidth = document.querySelector('.nowImg').offsetWidth;
      const picHeight = document.querySelector('.nowImg').offsetHeight;
      if (
        x + mirrorWidth / 2 < picWidth + 50 * nowSacle &&
        y + mirrorWidth / 2 < picHeight + 50 * nowSacle &&
        x - mirrorWidth / 2 > 0 - 50 * nowSacle &&
        y - mirrorWidth / 2 > 0 - 50 * nowSacle
      ) {
        // mirror 放大镜
        mirror.style.left = x - mirrorWidth / 2 + 'px';
        mirror.style.top = y - mirrorHeight / 2 + 'px';
        // const maxImgX = (x - 55) / 323 * 323 * nowSacle + 55 * (nowSacle - 1)
        // const maxImgY = (y - 55) / 430 * 430 * nowSacle + 55 * (nowSacle - 1)
        const maxImgX =
          ((x - mirrorWidth / 2) / nowImgWidth) * nowImgWidth * nowSacle + (mirrorWidth / 2) * (nowSacle - 1);
        const maxImgY =
          ((y - mirrorHeight / 2) / nowImgHeight) * nowImgHeight * nowSacle + (mirrorHeight / 2) * (nowSacle - 1);
        // 大图
        maxImg2.style.left = -maxImgX + 'px';
        maxImg2.style.top = -maxImgY + 'px';
      }
    },
  },
};
</script>

<style>
body * {
  margin: 0;
  padding: 0;
}

#moveBox {
  position: relative;
}

#mirror {
  position: absolute;
  overflow: hidden;
  height: 100px;
  width: 100px;
  /* border: 5px black solid; */
  cursor: crosshair;
  display: none;
}
.maxImg2 {
  position: absolute;
  max-width: inherit;
}
</style>
posted on 2021-09-08 15:20  佑之以航  阅读(69)  评论(0编辑  收藏  举报