vue图片预览

在这里插入图片描述
一般的可以用element-ui的Image来实现图片预览
但是如果是鼠标移上去在卡片上才出现图片并且需要预览,element会有一些bug,所以自己写一个
效果图:带切换,放大缩小旋转

<template>
    <div v-if="previewImg.popup" class="rlPopup">
      <div class="close-big-img" @click="close()">
        <i class="el-icon-close"></i>
      </div>
      <div class="prev handle-btn" v-if="!isSingle"  @click="prev()">
        <i class="el-icon-arrow-left"></i>
      </div>
      <div class="next handle-btn" v-if="!isSingle" @click="next()">
        <i class="el-icon-arrow-right"></i>
      </div>
      <!--放大缩小旋转-->
      <div class="zoom-wrap">
        <i @click="handleActions('zoomOut')" class="el-icon-zoom-out"></i>
        <i @click="handleActions('zoomIn')" class="el-icon-zoom-in"></i>
        <i @click="handleActions('left')" class="el-icon-refresh-left"></i>
        <i @click="handleActions('right')" class="el-icon-refresh-right"></i>
      </div>
      <div class="img-list-wrap">
        <div v-for="(img, i) in previewImg.imgList" :key="img">
          <img
            ref="img"
            :src="img"
            v-if="i === previewImg.index"
            :style="imgStyle"
            alt="">
        </div>
      </div>
    </div>
  </template>
  
  <script>
  export default {
    name: 'PreviewImage',
    props: {
      previewImg: {
        type: Object,
        default: () => {}
      }
    },
    data() {
      return {
        transform: {
          scale: 2,
          degree: 0
        }
      }
    },
    computed: {
      isSingle() {
        return this.previewImg.imgList.length <= 1
      },
      isFirst() {
        return this.previewImg.index === 0
      },
      isLast() {
        return this.previewImg.index === this.previewImg.imgList.length - 1
      },
      imgStyle() {
        const { scale, degree } = this.transform
        const style = {
          transform: `scale(${scale}) rotate(${degree}deg)`
        }
        return style
      }
    },
    methods: {
      prev() {
        if (this.isFirst && !this.previewImg.infinite) return
        if (this.$parent.companyPreview.index > 0) {
          const len = this.previewImg.imgList.length
          this.$parent.companyPreview.index = (this.$parent.companyPreview.index - 1 + len) % len
          this.reset()
        }
      },
      next() {
        if (this.isLast && !this.previewImg.infinite) return
        if (this.previewImg.imgList.length > this.$parent.companyPreview.index) {
          const len = this.previewImg.imgList.length
          this.$parent.companyPreview.index = (this.$parent.companyPreview.index + 1) % len
          this.reset()
        }
      },
      handleActions(action) {
        const { zoomRate, rotateDeg, enableTransition } = {
          zoomRate: 0.2,
          rotateDeg: 90,
          enableTransition: true
        }
        const { transform } = this
        switch (action) {
          case 'zoomOut':
            if (transform.scale > 0.2) {
              transform.scale = parseFloat((transform.scale - zoomRate).toFixed(3))
            }
            break
          case 'zoomIn':
            transform.scale = parseFloat((transform.scale + zoomRate).toFixed(3))
            break
          case 'left':
            transform.degree -= rotateDeg
            break
          case 'right':
            transform.degree += rotateDeg
            break
        }
        transform.enableTransition = enableTransition
      },
      reset() {
        this.transform = {
          scale: 2,
          degree: 0
        }
      },
      close() {
        this.$parent.companyPreview.popup = false
      }
    }
  }
  </script>
  
  <style lang="scss" scoped>
    // 查看大图
    .rlPopup {
      position: fixed;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.5);
      z-index: 999;
      .close-big-img {
        position: absolute;
        top: 20px;
        right: 5%;
        z-index: 10000;
        width: 44px;
        height: 44px;
        line-height: 44px;
        font-size: 24px;
        color: #fff;
        background-color: #606266;
        border-color: #fff;
        border-radius: 50%;
        text-align: center;
        cursor: pointer;
      }
  
      .handle-btn {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        width: 44px;
        height: 44px;
        line-height: 44px;
        font-size: 24px;
        color: #fff;
        background-color: #606266;
        border-color: #fff;
        border-radius: 50%;
        cursor: pointer;
        text-align: center;
        z-index: 10000;
      }
  
      .prev {
        left: 40px;
      }
  
      .next {
        right: 40px;
      }
  
      .img-list-wrap {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
  
        img {
          display: block;
          object-fit: scale-down;
          transition: all 0.3s;
          width: 480px;
          height: 320px;
        }
      }
  
      .zoom-wrap {
        position: absolute;
        bottom: 16px;
        left: 50%;
        transform: translateX(-50%);
        background-color: #606266;
        border-radius: 22px;
        z-index: 10000;
        width: 222px;
        height: 44px;
        line-height: 47px;
        padding: 0 23px;
  
        i {
          color: #ffffff;
          cursor: pointer;
          font-size: 22px;
          margin-right: 25px;
  
          &:last-child {
            margin-right: 0;
          }
        }
      }
    }
  </style>
  • 17
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值