vue中图片放大镜功能

1、在vue项目中不可避免的会做一个图片放大镜的弄能(例如、商城、店铺等),今天同事问了这个功能恰好以前写过,因此记录一下。

2、废话不多说直接上代码:

父组件中:

<template>
  <div>
    <imgZoom class="imgZoom" v-if="imgpic" :url="imgpic" :highUrl="imgpic"></imgZoom>
  </div>
</template>
<script>
import imgZoom from '@/components/imgZoom.vue'
export default {
  data() {
    return {
      imgpic: null
    };
  },
components: {
    imgZoom
  },
}
</script>
<style>
.imgZoom {
    width: 400px;
    height: 400px;
}
 
</style>

子组件部分:

<template>
  <div class="pic-img">
    <div class="img-container" @mousemove="!moveEvent && mouseMove($event)" @mouseleave="!leaveEvent && mouseLeave($event)">
      <img ref="img" @load="imgLoaded" :src="url" style="width:400px" />
      <div
        v-if="!hideZoom && imgLoadedFlag"
        :class="['img-selector', { circle: type === 'circle' }]"
        :style="[imgSelectorSize, imgSelectorPosition, !outShow && imgSelectorBg, !outShow && imgBgPosition]"
      ></div>
      <div v-if="outShow" v-show="!hideOutShow" class="img-out-show" :style="[imgOutShowSize, imgSelectorBg, imgBgPosition]"></div>
    </div>
  </div>
</template>
 
<script>
export default {
  name: 'vue-photo-zoom-pro',
  data() {
    return {
      selector: {
        width: 166,
        halfWidth: 83,
        top: 0,
        left: 0,
        bgTop: 0,
        bgLeft: 0,
        rightBound: 0,
        bottomBound: 0,
        absoluteLeft: 0,
        absoluteTop: 0
      },
      imgInfo: {},
      hideOutShow: true,
      imgLoadedFlag: false,
      screenWidth: document.body.clientWidth,
      timer: null
      // url: '../static/img/zz.jpg',
      // highUrl: '../static/img/zz.jpg'
    }
  },
  props: {
    url: String,
    highUrl: String,
    type: {
      type: String,
      default: 'square',
      validator: function(value) {
        return ['circle', 'square'].indexOf(value) !== -1
      }
    },
    scale: {
      type: Number,
      default: 2
    },
    moveEvent: {
      type: [Object, MouseEvent],
      default: null
    },
    leaveEvent: {
      type: [Object, MouseEvent],
      default: null
    },
    hideZoom: {
      type: Boolean,
      default: false
    },
    outShow: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    moveEvent(e) {
      this.mouseMove(e)
    },
    leaveEvent(e) {
      this.mouseLeave(e)
    },
    url() {
      this.imgLoadedFlag = false
    },
    screenWidth(val) {
      if (!this.timer) {
        this.screenWidth = val
        this.timer = setTimeout(() => {
          this.imgLoaded()
          clearTimeout(this.timer)
          this.timer = null
        }, 400)
      }
    }
  },
  computed: {
    imgSelectorPosition() {
      let { top, left } = this.selector
      return {
        top: `${top}px`,
        left: `${left}px`
      }
    },
    imgSelectorSize() {
      let width = this.selector.width
      return {
        width: `${width}px`,
        height: `${width}px`
      }
    },
    imgOutShowSize() {
      let {
        scale,
        selector: { width }
      } = this
      return {
        width: `${width * scale}px`,
        height: `${width * scale}px`
      }
    },
    imgSelectorBg() {
      let {
        scale,
        url,
        highUrl,
        imgInfo: { height, width }
      } = this
      return {
        backgroundImage: `url(${highUrl || url})`,
        backgroundSize: `${width * scale}px ${height * scale}px`
      }
    },
    imgBgPosition() {
      let { bgLeft, bgTop } = this.selector
      return {
        backgroundPosition: `${bgLeft}px ${bgTop}px`
      }
    }
  },
  methods: {
    imgLoaded() {
      let imgInfo = this.$refs['img'].getBoundingClientRect()
      if (JSON.stringify(this.imgInfo) == JSON.stringify(imgInfo)) {
        // 位置不变不更新
        return
      }
      this.imgLoadedFlag = true
      let { width, height, left, top } = (this.imgInfo = imgInfo)
      let selector = this.selector
      let { width: selectorWidth, halfWidth: selectorHalfWidth } = selector
      let { scrollLeft, scrollTop } = document.documentElement
      selector.rightBound = width - selectorWidth
      selector.bottomBound = height - selectorWidth
      selector.absoluteLeft = left + selectorHalfWidth + scrollLeft
      selector.absoluteTop = top + selectorHalfWidth + scrollTop
    },
    reset() {
      Object.assign(this.selector, {
        top: 0,
        left: 0,
        bgLeft: 0,
        bgTop: 0
      })
    },
    mouseMove(e) {
      if (!this.hideZoom && this.imgLoadedFlag) {
        this.imgLoaded() //防止img位置变化
        let { pageX, pageY } = e
        let { scale, selector } = this
        let { halfWidth, absoluteLeft, absoluteTop, rightBound, bottomBound } = selector
        let x = pageX - absoluteLeft // 选择器的x坐标 相对于图片
        let y = pageY - absoluteTop // 选择器的y坐标
        if (this.outShow) {
          halfWidth = 0
          this.hideOutShow = false
        }
        selector.top = y > 0 ? (y < bottomBound ? y : bottomBound) : 0
        selector.left = x > 0 ? (x < rightBound ? x : rightBound) : 0
        selector.bgLeft = halfWidth - (halfWidth + x) * scale // 选择器图片的坐标位置
        selector.bgTop = halfWidth - (halfWidth + y) * scale
      }
    },
    mouseLeave() {
      if (this.outShow) {
        this.hideOutShow = true
      }
    }
  }
}
</script>
<style scoped>
.img-container {
  position: relative;
}
 
.img-selector {
  background-color: rgba(0, 0, 0, 0.6);
  position: absolute;
  background-repeat: no-repeat;
  cursor: crosshair;
  border: 1px solid rgba(0, 0, 0, 0.1);
}
 
.img-selector.circle {
  border-radius: 50%;
}
 
.img-out-show {
  position: absolute;
  top: 0;
  right: 0;
  background-repeat: no-repeat;
  transform: translate(100%, 0);
  border: 1px solid rgba(0, 0, 0, 0.1);
}
</style>

备注:

:url="imgpic" 

:highUrl="imgpic"

两个表示需要展示和放大的图片,需统一

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 2.7版本的图片放大镜同样可以使用magnify插件实现。下面是一个Vue 2.7版本实现图片放大镜的示例代码: 1. 在Vue组件引入所需的CSS和JS文件,例如:jquery、magnify等; 2. 在Vue组件定义需要放大的图片,例如: ```html <template> <div class="container"> <img src="./assets/img/product.jpg" alt="Product" class="product-img" id="product-img"> </div> </template> ``` 3. 在Vue组件的mounted()钩子函数初始化放大镜功能,例如: ```javascript mounted() { $(document).ready(function() { $('#product-img').magnify({ speed: 200, src: './assets/img/product-large.jpg', onload: function() { console.log('Magnify Loaded'); } }); }); } ``` 在上述代码,我们使用jQuery选择器选择了需要放大的图片,并使用magnify插件初始化放大镜功能。 4. 最后,在Vue组件的CSS样式定义放大镜的样式,例如: ```css .product-img { width: 100%; max-width: 500px; cursor: zoom-in; } .magnify-lens { position: absolute; display: none; border: 1px solid #d4d4d4; background-color: #fff; opacity: .5; width: 100px; height: 100px; cursor: move; } .magnify-preview { position: absolute; overflow: hidden; display: none; z-index: 999; width: 400px; height: 400px; border: 1px solid #d4d4d4; background-color: #fff; opacity: .5; } ``` 在上述代码,我们定义了放大镜镜片和预览框的样式,可以根据需求进行定制。需要注意的是,在Vue 2.7版本,mounted()钩子函数使用jQuery选择器需要在前面加上$符号,例如:$('#product-img')。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值