According to the requirements of one of the company’s projects, the avatar modification function can be realized according to the UI diagram. Click the avatar to edit, and the avatar modification box will pop up, which requires cutting and real-time preview.

  • Without further ado, first a wave of renderings:

Before selecting an image

After selecting the image

Implementation code:

<template>
  <el-dialog
    title="Edit avatar"
    :visible.sync="dialogVisible"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    width="600px"
  >
    <div style="display: flex" class="avatar">
      <div class="avatar-left">
        <div v-show=! "" options.img">
          <el-upload
            ref="upload"
            action=""
            style="text-align: center; margin-bottom: 24px"
            :on-change="uploads"
            accept="image/png, image/jpeg, image/jpg"
            :show-file-list="false"
            :auto-upload="false">
            <el-button slot="trigger" size="small" type="primary" ref="uploadBtn">Choose picture</el-button>
          </el-upload>
          <div>JPG or PNG images, the size of which cannot exceed 3M</div>
        </div>
        <div v-show="options.img" class="avatar-left-crop">
          <vueCropper
            class="crop-box"
            ref="cropper"
            :img="options.img"
            :autoCrop="options.autoCrop"
            :fixedBox="options.fixedBox"
            :canMoveBox="options.canMoveBox"
            :autoCropWidth="options.autoCropWidth"
            :autoCropHeight="options.autoCropHeight"
            :centerBox="options.centerBox"
            @realTime="realTime">
          </vueCropper>
          <p class="avatar-left-p">Mouse wheel zoom control picture display size, mouse drag adjust display position</p>
        </div>
      </div>
      <div class="avatar-right">
        <div class="avatar-right-div" v-for="item in previewsDiv" :style="item.style">
          <div v-show="options.img" :class="previews.div" class="avatar-right-previews" :style="item.zoomStyle">
            <img :src="previews.url" :style="previews.img">
          </div>
        </div>
        <div class="avatar-right-text">
          <el-button v-if="options.img" type="text" @click="uploadPreviews">Upload again</el-button>
          <span v-else>preview</span>
        </div>
      </div>
    </div>
    <span slot="footer" class="dialog-footer">
    <el-button @click="closeDialog">Take away</el-button>
    <el-button type="primary" @click="getCrop">determine</el-button>
  </span>
  </el-dialog>
</template>

<script>
  export default {
    name: "avatarEdit".props: {
      dialogVisible: {
        type: Boolean.default: false}},data() {
      return {
        //vueCropper component clipping configuration information
        options: {
          img: ' '.// Original image file
          autoCrop: true.// A screenshot box is generated by default
          fixedBox: true.// Fix the size of the screenshot frame
          canMoveBox: false.// The screenshot box cannot be dragged
          autoCropWidth: 200.// Capture the width of the box
          autoCropHeight: 200.// The height of the screenshot
          centerBox: true.// The screenshot box is restricted to the image
        },
        // Preview graph data in real time
        previews: {},
        // Live preview the image style
        previewsDiv: [
          //108px preview style
          {
            style: {
              width: '108px'.height: '108px'.margin: '0 auto'
            },
            zoomStyle: {
              zoom: 0.54}},//68px preview style
          {
            style: {
              width: '68px'.height: '68px'.margin: '27px auto'
            },
            zoomStyle: {
              zoom: 0.34}},//48px preview style
          {
            style: {
              width: '48px'.height: '48px'.margin: '0 auto'
            },
            zoomStyle: {
              zoom: 0.24}}],}},methods: {
      // Read the original image
      uploads(file) {
        const isIMAGE = file.raw.type === 'image/jpeg' || file.raw.type === 'image/png';
        const isLt3M = file.raw.size / 1024 / 1024 < 3;
        if(! isIMAGE) {this.$message({
            showClose: true.message: 'Please select JPG, PNG image! '.type: 'error'.// Prompt type
          });
          return false;
        }
        if(! isLt3M) {this.$message({
            showClose: true.message: 'Upload image size cannot exceed 3MB'.type: 'error'.// Prompt type
          });
          return false;
        }
        let reader = new FileReader();
        reader.readAsDataURL(file.raw);
        reader.onload = e= > {
          this.options.img = e.target.result //base64}},// Preview data in real time
      realTime(data) {
        this.previews = data
      },
      // Re-upload
      uploadPreviews() {
        this.$refs.uploadBtn.$el.click()
      },
      // Obtain the screenshot information
      getCrop() {
        // Obtain the base64 data of the screenshot
        this.$refs.cropper.getCropData((data) = > {
          console.log(data)
        })
        // Get the bloB data of the screenshot
        this.$refs.cropper.getCropBlob((data) = > {
          console.log(data)
        })
      },
      // Close the dialog box
      closeDialog() {
        // Call the parent component closeAvatarEdits()
        this.$parent.closeAvatarEdits()
        // Reset data. Object.assign is a deep copy of the Object. This.$data is the data Object in the component.
        Object.assign(this.$data, this.$options.data())
      },
    }
  }
</script>

<style lang="scss" scoped>

  /deep/ .el-dialog__header {
    padding: 24px 0 11px 28px;
  }

  /deep/ .el-dialog__title {
    color: # 333333;
  }

  /deep/ .el-dialog__body {
    padding: 0 28px;
  }

  /deep/ .el-dialog__footer {
    padding: 20px 28px;

    .el-button {
      width: 145px; }}.avatar {
    display: flex;

    .avatar-left {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 400px;
      height: 400px;
      background-color: #F0F2F5;
      margin-right: 10px;
      border-radius: 4px;

      .avatar-left-crop {
        width: 400px;
        height: 400px;
        position: relative;

        .crop-box {
          width: 100%;
          height: 100%;
          border-radius: 4px;
          overflow: hidden
        }

      }

      .avatar-left-p {
        text-align: center;
        width: 100%;
        position: absolute;
        bottom: 20px;
        color: #ffffff;
        font-size: 14px; }}.avatar-right {
      width: 150px;
      height: 400px;
      background-color: #F0F2F5;
      border-radius: 4px;
      padding: 16px 0;
      box-sizing: border-box;

      .avatar-right-div {
        border: 3px solid #ffffff;
        border-radius: 50%;
      }

      .avatar-right-previews {
        width: 200px;
        height: 200px;
        overflow: hidden;
        border-radius: 50%;
      }

      .avatar-right-text {
        text-align: center;
        margin-top: 50px;
        font-size: 14px;

        /deep/ .el-button {
          padding: 0;
        }

        span {
          color: # 666666; }}}}</style>

Copy the code
  • UI library element
  • Photo clipping plugin vueCropper
  • Upload image to element —-upload

My CSDN → portal

Every article is full of dry goods, no advertising and nonsense! Welcome to like + follow + favorites