vue3 商品详情 图片放大镜

<template>
  <div class="wrap">
    <div class="origin" :style="{
        width: `${initWidth}px`,
        height: `${initHeight}px`,
      }">
      <div class="event-view" @mouseenter="mouseenter" @mousemove="mousemove" @mouseleave="mouseleave"></div>
      <img class="img" :src="url">
      <div class="mask" v-show="data.show" :style="{
        width: `${initWidth / zoom}px`,
        height: `${initHeight / zoom}px`,
        left: `${data.maskLeft}px`,
        top: `${data.maskTop}px`,
      }"></div>
    </div>

    <div class="per-view" v-show="data.show" :style="{
        width: `${initWidth}px`,
        height: `${initHeight}px`,
      }">
      <img class="img" :style="{
        width: `${initWidth * zoom}px`,
        height: `${initHeight * zoom}px`,
        left: `${data.perviewLeft}px`,
        top: `${data.perviewTop}px`,
      }" :src="url" />
    </div>
  </div>
</template>

<script setup>
import { reactive, defineProps } from 'vue'
const props = defineProps({
  zoom: {
    type: Number,
    default: 2
  },
  url: {
    type: String,
    required: true,
    default: "https://temp.im/200x200/4CD964/fff"
  },
  initWidth: {
    type: Number,
    default: 400
  },
  initHeight: {
    type: Number,
    default: 400
  },
})
const data = reactive({
  show: false,
  maskLeft: 0,
  maskTop: 0,
  perviewLeft: 0,
  perviewTop: 0
})

const mouseenter = () => {
  data.show = true;
}

const mousemove = (e) => {
  const { offsetX, offsetY } = e;
  const { initWidth, initHeight, zoom } = props;
  const maskWidth = initWidth / zoom;
  const maskHeight = initHeight / zoom;
  let viewX,viewY;
  viewX = offsetX - (maskWidth / 2);
  viewY = offsetY - (maskHeight / 2);

  // 边界判断
  viewX = viewX < 0 ? 0 : viewX;
  viewY = viewY < 0 ? 0 : viewY;
  if(viewX + maskWidth >= initWidth) {
    viewX = initWidth - maskWidth;
  }
  if(viewY + maskHeight >= initHeight) {
    viewY = initHeight - maskHeight;
  }

  data.maskLeft = viewX
  data.maskTop = viewY
  data.perviewLeft = -viewX * props.zoom;
  data.perviewTop = -viewY * props.zoom;
}

const mouseleave = () => {
  data.show = false;
}

</script>
<style lang="scss" scoped>
.wrap {
  display: flex;
}
.origin {
  position: relative;
  .event-view {
    position: absolute;
    width: 100%;
    height: 100%;
    z-index: 999;
  }
  .img {
    width: 100%;
    height: 100%;
  }
  .mask {
    position: absolute;
    background: rgba(255,255,255,.4);
  }
}
.per-view {
  position: relative;
  margin-left: 20px;
  overflow: hidden;
  .img {
    position: absolute;
  }
}
</style>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值