vue 预览图片封装上下切换预览功能封装处理

vue 预览图片封装上下切换预览功能封装处理

点击图片放大,再点击关闭实现很简单,但是当多个图预览时候,能自带切换体验会更好一些。
本文使用ant-design-vue作为项目案例

父组件调用:

<!-- 预览 -->
    <a-modal :visible="previewImgVisible" :footer="null" centered width="auto" @cancel="handleCancel">
      <Review :path="previewImgUrl" :pathList="previewImgUrlList" />
    </a-modal>
data() {
    return {
      previewImgVisible: false, // 查看附件图片
      previewImgUrl: '',
      previewImgUrlList: [], //预览图片列表
    }
  },
  methods: {
  // 关闭预览
    handleCancel() {
      this.previewImgVisible = false;
    },
    // 预览图片
    handlePreview(url) {
      this.previewImgUrl = url;
      this.previewImgVisible = true;
      this.previewImgUrlList = ['url1', 'url2', 'url3']
    },
  }

预览子组件

Review.vue

<template>
  <div
    class="cp-view"
    :style="{
      width: (width < 500 ? 500 : width) + 50 + 'px',
      height: (height < 300 ? 300 : height) + 50 + 'px',
    }"
  >
    <div class="photo-box flex-row-center-center" @mousewheel="onWheel">
      <img
        :class="['photo-item', isCovered && 'drag']"
        ref="photoRef"
        :src="currentPath"
        alt=""
        @mousedown="onDrag"
        :style="{ transform: `rotate(${rotateDeg}deg) scale(${scale})` }"
      />
    </div>
    <div class="photo-btns flex-row-center-center">
      <a-icon
        class="pointer fs-22 m-r-30"
        type="zoom-in"
        @click="onScale(0.1)"
      />
      <a-icon
        class="pointer fs-22 m-r-30"
        type="zoom-out"
        @click="onScale(-0.1)"
      />
      <span
        :class="['pointer', 'reset-btn', 'm-r-30', scale === 1 && 'disabled']"
        @click="scale = 1"
        >1:1</span
      >
      <a-icon class="pointer fs-22" type="redo" @click="onRotate" />
    </div>
    <a-icon
      :class="['icon-left', pathList.indexOf(currentPath) === 0 && 'disabled']"
      @click="handleSwiper(-1)"
      type="left-circle"
    />
    <a-icon
      :class="[
        'icon-right',
        pathList.indexOf(currentPath) === pathList.length - 1 && 'disabled',
      ]"
      @click="handleSwiper(1)"
      type="right-circle"
    />
  </div>
</template>

<script>
export default {
  props: {
    path: {
      type: String,
      default: '',
    },
    pathList: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      currentPath: this.path,
      rotateDeg: 0,
      width: 0,
      height: 0,
      cWidth: 0,
      cHeight: 0,
      scale: 1,
      isCovered: false,
      imgRef: this.$refs.photoRef,
    };
  },
  mounted() {
  },
  methods: {
    // 图片前后切换
    handleSwiper(prevOrNext) {
      const index = this.pathList.indexOf(this.currentPath)
      if ((index === this.pathList.length - 1 && prevOrNext === 1) || (index === 0 && prevOrNext === -1)) return
      console.log(index)
      if (prevOrNext === -1) {
        this.currentPath = this.pathList[index - 1]
      } else if (prevOrNext === 1) {
        this.currentPath = this.pathList[index + 1]
      }
    },
    onDrag(e) {
      const img = this.$refs.photoRef;
      e.preventDefault();
      const l = e.clientX - img.offsetLeft;
      const t = e.clientY - img.offsetTop;
      document.onmousemove = function (e) {
        img.style.left = e.clientX - l + 'px';
        img.style.top = e.clientY - t + 'px';
      };
      img.onmouseup = function () {
        document.onmousemove = null;
        img.onmouseup = null;
      };
    },
    onRotate() {
      this.rotateDeg += 90;
      if (this.rotateDeg >= 360) {
        this.rotateDeg = 0;
      }
      const img = this.$refs.photoRef;
      if (this.rotateDeg === 90 || this.rotateDeg === 270) {
        if (this.cWidth > this.cHeight) {
          // 宽大于高
          img.width = this.height;
        } else if (this.cWidth < this.cHeight) {
          // 宽小于高
          img.height = this.height;
        }
      } else {
        // 还原
        if (this.cWidth > this.cHeight) {
          // 宽大于高
          img.width = this.width;
        } else if (this.cWidth < this.cHeight) {
          // 宽小于高
          img.height = this.height;
        }
      }
    },
    onScale(val) {
      if (val < 0 && this.scale <= 0.2) {
        return;
      }
      if (val > 0 && this.scale >= 4) {
        return;
      }
      this.scale += val;
    },
    onWheel(e) {
      if (e.deltaY > 0) {
        this.onScale(-0.1);
      } else if (e.deltaY < 0) {
        this.onScale(0.1);
      }
    },
  },
  watch: {
    currentPath: {
      immediate: true,
      deep: true,
      handler: function (val) {
        this.rotateDeg = 0;
        const img = document.createElement('img');
        img.src = val || '';
        img.onload = () => {
          let w = (this.cWidth = img.width);
          let h = (this.cHeight = img.height);
          if (w > 1000) {
            w = 1000;
          }
          if (h > 500) {
            h = 500;
          }
          if (w < 500) {
            h = 500;
          }
          if (h < 300) {
            h = 300;
          }
          this.width = w;
          this.height = h;
        };
      },
    },
    scale: {
      handler: function (val) {
        const img = this.$refs.photoRef;
        if (
          img.width * val > this.width + 50 ||
          img.height * val > this.height + 50
        ) {
          this.isCovered = true;
        } else {
          this.isCovered = false;
        }
      },
    },
  },
};
</script>

<style lang="less" scoped>
.cp-view {
  position: relative;
  margin-bottom: 40px;
  &:hover {
    .icon-left,
    .icon-right {
      display: block;
    }
  }
  .icon-left,
  .icon-right {
    user-select: none;
    position: absolute;
    font-size: 34px;
    cursor: pointer;
    top: 50%;
    transform: translateY(-50);
    display: none;
    &.disabled {
      color: #999;
      cursor: not-allowed;
    }
  }
  .icon-left {
    left: 0;
  }
  .icon-right {
    right: 0;
  }
  // overflow: hidden;
  .photo-box {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: relative;
    .photo-item {
      position: absolute;
      max-height: 500px;
      max-width: 1000px;
      display: block;
      &.drag {
        cursor: move;
      }
    }
  }
  .photo-btns {
    width: 100%;
    user-select: none;
    position: absolute;
    bottom: -40px;
    .reset-btn {
      padding: 1px 5px;
      margin-top: -3px;
      background: #00be7e;
      border: 1px solid #00be7e;
      border-radius: 2px;
      color: #fff;
      &.disabled {
        border-color: #ccc;
        background: none;
        color: #333;
        cursor: default;
      }
    }
  }
}
</style>

效果如下:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值