elementui ImagePicker

吴鸿禧
2023-12-01

学习记录:
需求:定义一个图片上传/预览/放大效果公共组件。

<template>
  <div class="image-picker">
    <!-- 文字时 -->
    <span v-if="viewImgTitle" @click="viewBigImg" class="view-image-title">{{viewImgTitle}}</span>
    <!-- 图片展示形式 -->
    <div
      :class="['avatar-uploader', {'avatar-uploader_border' : avaterUploadImg}, {'cursor' : !isNeedUpload}]"
      :style="{'width':width,'height':height}"
      @click="viewBigImg('img')"
      v-else
    >
      <!-- 编辑时 -->
      <img
        v-if="avaterUploadImg"
        :src="avaterUploadImg"
        class="avatar"
        :style="{'width' : width, height: 'auto'}"
      />
      <div v-if="avaterUploadImg && isNeedUpload" class="avatar-edit">
        <div class="avatar-edit_magnifier" @click.stop="viewBigImg">
          <svg-icon icon-class="ic-view" class="ic_edit"></svg-icon>
        </div>
        <span class="avatar-edit_line">|</span>
        <div class="avatar-edit_replace" @click.stop="$refs['input'].click()">
          <svg-icon :icon-class="editIconAndTitle.editIcon" class="ic_edit margin-right_8"></svg-icon>
          <span>{{editIconAndTitle.editTitle}}</span>
        </div>
      </div>
      <!-- 新增时的+ -->
      <div
        v-if="!avaterUploadImg && isNeedUpload"
        class="avatar-uploader-icon"
        @click.stop="$refs['input'].click()"
        :style="{'width':width,'height':height}"
      >
        <i class="el-icon-plus"></i>
      </div>
    </div>
    <slot name="tip"></slot>
    <!-- 上传文件 -->
    <input type="file" ref="input" @change="imageChange" :accept="accept" style="display:none;" />
    <!-- 放大查看 -->
    <el-image-viewer
      v-if="showViewer"
      :urlList="preViewSrcList"
      :on-close="closeViewer"
      :zIndex="2020"
    ></el-image-viewer>
  </div>
</template>

引入

import elImageViewer from "element-ui/packages/image/src/image-viewer.vue";
<script>
import elImageViewer from "element-ui/packages/image/src/image-viewer.vue";
export default {
  components: {
    elImageViewer
  },
  props: {
    viewImgTitle: {
      // 默认为图片查看  有的话就是文字
      type: String,
      default: ""
    },
    isNeedUpload: {
      // 是否需要上传   false的话 不能上传 只能点击放大
      type: Boolean,
      default: true
    },
    isBase64: {
      // 返回出去的是否是base64字符串
      type: Boolean,
      default: false
    },
    editIconAndTitle: {
      type: Object,
      default: () => {
        return {
          editIcon: "ic-white-edit",
          editTitle: "Edit"
        };
      }
    },
    uploadImg: {
      // 开始传递的图片
      default: ""
    },
    // 可以上传的类型
    accept: {
      type: String,
      default: "image/png, image/jpeg, image/jepg"
    },
    width: {
      type: String || Number,
      default: "100%"
    },
    height: {
      type: String || Number,
      default: "100%"
    },
    // 没有图片时的错误提示
    messageWarning: {
      type: String,
      default: "No image, please upload it first"
    }
  },
  computed: {
    fileSelecter() {
      return this.$refs["input"];
    }
  },
  data() {
    return {
      avaterUploadImg: "", // 组件存储的图片
      showViewer: false,
      preViewSrcList: []
    };
  },
  watch: {
    uploadImg: {
      handler: function(newVal, oldVal) {
        this.avaterUploadImg = newVal;
      }
    }
  },
  created() {
    this.avaterUploadImg = this.uploadImg;
  },
  methods: {
    // 上传/更改图片
    imageChange($event) {
      if ($event["target"]["files"].length === 0) return;
      const selectFile = $event["target"]["files"][0];
      let flag = this.beforeAvatarUpload(selectFile);
      if (flag) {
        this.avaterUploadImg = window.URL.createObjectURL(selectFile);
        if (this.isBase64) {
          // 将图片转换为base64 暴露出去
          this.imageToBase64(selectFile).then(res => {
            this.$emit("imageChange", res);
          });
        } else {
          // 将图片暴露出去
          this.$emit("imageChange", selectFile);
        }
      }
    },
    // 开启预览
    viewBigImg(val) {
      if (val === "img" && this.isNeedUpload) return; // 如果需要上传 点击图片 不放大
      if (!this.avaterUploadImg) {
        this.$message.warning(this.messageWarning);
        return;
      }
      this.showViewer = true;
      this.preViewSrcList = [this.avaterUploadImg];
      window.document.body.style.overflow = "hidden";
      this.$emit("viewBigImg");
    },
    // 关闭预览图片
    closeViewer() {
      this.showViewer = false;
      this.preViewSrcList = [];
      window.document.body.style.overflow = "auto";
      this.$emit("closeViewer");
    },
    // 上传之前做校验
    beforeAvatarUpload(file) {
      const isFitFormats =
        file.type === "image/png" ||
        file.type === "image/jpeg" ||
        file.type === "image/jepg";
      const isLt5M = file.size / 1024 / 1024 < 5;

      if (!isFitFormats) {
        this.$message.error(
          "The uploaded image can only be in jpg/jpeg/png format"
        );
      }
      if (!isLt5M) {
        this.$message.error("The uploaded image size cannot exceed 5MB");
      }
      return isFitFormats && isLt5M;
    },
    imageToBase64(img) {
      return new Promise((resolve, reject) => {
        let reader = new FileReader(); //新建一个FileReader对象
        reader.readAsDataURL(img); //将读取的文件转换成base64格式
        reader.onload = function(e) {
          resolve(e.target.result);
        };
      });
    }
  }
};
</script>

自定义调整样式

<style lang="less" scoped>
.image-picker {
  display: inline-block;
  .view-image-title {
    cursor: pointer;
  }
  .avatar-uploader {
    border: 1px dashed #d8dce6;
    background-color: #ffffff;
    border-radius: 6px;
    line-height: 160px;
    position: relative;
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    .avatar-uploader-icon {
      font-size: 28px;
      color: #8c939d;
    }
    .avatar-edit {
      width: 100%;
      height: 32px;
      background: rgba(0, 0, 0, 0.5);
      border-radius: 0 0 4px 4px;
      position: absolute;
      bottom: 0;
      left: 0;
      color: #fff;
      display: flex;
      align-items: center;
      line-height: 32px;
    }
    .avatar-edit_magnifier {
      cursor: pointer;
      width: 44px;
      height: 32px;
    }
    .avatar-edit_line {
      width: 5px;
      height: 16px;
      line-height: 16px;
    }
    .avatar-edit_replace {
      flex: 1;
      height: 100%;
      cursor: pointer;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      color: #ffffff;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .ic_edit {
      width: 14px;
      height: 14px;
      vertical-align: middle;
    }
    .logo-reminder {
      margin-top: 5px;
      font-family: Helvetica;
      font-size: 12px;
      color: #606266;
      line-height: 18px;
      .logo-reminder_detail {
        display: block;
        margin: 0 auto;
        width: 200px;
      }
    }
  }
  .avatar-uploader.avatar-uploader_border {
    border: 1px solid #d8dce6;
    background-color: #f5f7fa;
  }
  .margin-right_8 {
    margin-right: 8px;
  }
  .cursor {
    cursor: pointer;
  }
  /deep/.el-image-viewer__wrapper .el-image-viewer__canvas > img {
    background-color: #f5f7fa;
  }
  /deep/.el-icon-circle-close{
    color: #FFF
  }
}
</style>

页面调用:例1 预览+上传

<el-form-item label="logo:" prop="logo">
    <ImagePicker
      :uploadImg="logo"
      @imageChange="imageChange"
      width="160px"
      height="160px"
      :isBase64="true"
      key="add-logo"
    >
      <div
        slot="tip"
        class="upload-tip"
      >Suport jpg/jpeg/png formats,the size should not exceed 5M.</div>
    </ImagePicker>
  </el-form-item>

例2: 预览不上传

//:editIconAndTitle="{'editIcon': 'ic-reupload', 'editTitle': 'Re-upload'}"
<ImagePicker       
  :uploadImg="obj['signature']"
  :isNeedUpload="false"
  class="margin-left-right_4"
  width="160px"
  height="160px"
  key="patient-signature"
></ImagePicker>
imageChange(val) {
   // 赋值
   this.form["loge"] = val;
 },
 类似资料:

相关阅读

相关文章

相关问答