Because of the need to use vUE plug-in VUe-cropper for picture clipping.

The installation

npm install vue-cropper
Copy the code

use

import VueCropper from vue-cropper
Copy the code

rendering

This time, the main use of element-UI + vue-Cropper to accomplish this requirement, not to talk about the code.

<div>
    <el-upload
          :action="" '"
          list-type="picture-card"
          :file-list="MastergraphPicList"
          :limit="10"
          :on-change='changeUpload'
          :auto-upload="false"
          :show-file-list="isFlag"
          :http-request="ServiceUpLoad"
          :on-success="(response,file,fileList) => handlePostSuccess(response,file,fileList)"
          :on-remove="(response,file,fileList) => handleDelete(response,file,fileList)"
          >
          <i class="el-icon-plus"></i>
          <div slot="tips" class="el-upload__tip"</div> </el-upload> </div> </div>Copy the code

The changeUpload hook function is triggered when an image is uploaded, and since clipping images is triggered in the form of pop-ups, our actions can be written in this hook function.

changeUpload(file, fileList) { <! -- Limit file format, size --> const isLt2M = file.size / 1024/1024 < 2if(! isLt2M) { this.$message.error('Upload file size cannot exceed 2MB! ')
          return false} <! Echo - written list -- > this. MastergraphPicList. Push (file); <! Trigger child method, invoke clipping box --> this.$children[0].isShow();
      },
Copy the code

Clipping box template cropper.vue

<template>
    <div>
        <el-dialog title="Picture cropping" :visible.sync="dialogVisible" append-to-body>
        <div class="cropper-content">
            <div class="cropper" style="text-align:center">
            <vueCropper
                ref="cropper"
                :img="option.img"
                :outputSize="option.size"
                :outputType="option.outputType"
                :info="true"
                :full="option.full"
                :canMove="option.canMove"
                :canMoveBox="option.canMoveBox"
                :original="option.original"
                :autoCrop="option.autoCrop"
                :fixed="option.fixed"
                :fixedNumber="option.fixedNumber"
                :centerBox="option.centerBox"
                :infoTrue="option.infoTrue"
                :fixedBox="option.fixedBox"
            ></vueCropper>
            </div>
        </div>
        <div slot="footer" class="dialog-footer">
            <el-button @click="cancel"</el-button> <el-buttontype="primary" @click="finish" :loading="loading"</el-button> </div> </el-dialog> </div> </template> <script> import axios from'axios'
import { VueCropper } from 'vue-cropper'
import md5 from 'js-md5';
import { postossImage } from '.. /.. /.. /api/index'
    export default {
        name:'cropper'.data() {
            return// Clipping the base configuration of the component option: {img:' '// Clipping the image info:trueOutputType: 0.8, // outputType: 0.8'jpeg'// Crop the generated image to canScale:true// Does the image allow the wheel to zoom the autoCrop:trueAutoCropWidth: 600, autoCropHeight: 300, fixedBox:false// The size of the screenshot box cannot be changed.false, // Whether to enable fixedNumber: [7, 5], // Full:trueCanMoveBox:true, // Can you drag the screenshot box original:true// Upload the image and render it to the original scale.true,
                    centerBox: true// Whether the screenshot box is restricted to the image infoTrue:true // trueTo show the true output picture width and heightfalse}, picsList: [], // page display array // prevent repeated commit loading:false,
                dialogVisible:falseFileinfo :[], RequestSource:' ', // baseurl:' ', // Base64 address trimmed isVictory:false}}, components:{VueCropper},created() {
            this.$on('is-Show',this.isShow); }, methods:{ isShow(file){ this.fileinfo = file; // Pass in the clipped address and open this as a popbox.$nextTick( () => {
                    this.option.img = file.url;
                    this.dialogVisible = true; this.handlePostSuccess(file.url); }, // turn off image clippingcancel() {
                this.dialogVisible = false; // Remove the echo image this when you click Cancel.$parent.dislodge(this.fileinfo); }, // Confirm clipping triggersfinish() {
                this.$refs.cropper.getCropData((data) => { this.baseurl = data; // Convert the cropped base64 image to file formatletfile = this.convertBase64UrlToBlob(data) file.name = this.fileinfo.name <! --let file = URL.createObjectURL(data).match(/[^blob:]+/g).join(' '); --> this.Directpass(this.RequestSource,file).then( (res) => {if (res.status === 200) {
                            this.$parent.handleSuccess({
                                uid:this.fileinfo.uid,
                                imgUrl:res.config.url.split('? ')[0]
                            });
                            this.dialogVisible = false;
                            this.isVictory = true;
                            this.loading = true;
                            this.$message('Upload successful! '); // Prevent users from uploading images and clicking closesetTimeout(() => {
                                this.isVictory = false; },1000)}})})}, HandlePostSuccess (file) {postossImage({fileMd5: MD5 (file)}). Then ((res) => {this.requestSource = res.data; }) }, Directpass(url,file){return new Promise( (resolve,reject) => {
                axios.put(url,file,{headers:{"x-oss-meta-author":"deshe"."Content-Type":"application/octet-stream"}}). Then ((res) => {resolve(res)})})}, // Convert base64 to file file convertBase64UrlToBlob(urlData) {let bytes = window.atob(urlData.split(', ') [1]); // Remove the url header and convert it to byte // handle exceptions, converting ASCII less than 0 to greater than 0let ab = new ArrayBuffer(bytes.length);
            let ia = new Uint8Array(ab);
            for (var i = 0; i < bytes.length; i++) {
                ia[i] = bytes.charCodeAt(i);
            }
            return new Blob([ab], { type: 'image/jpeg' });
        }
    },
    watch:{
        dialogVisible() {
            if(! this.dialogVisible && ! this.isVictory) { this.loading =false// Remove the echo image this when clicking Close.$parent.dislodge(this.fileinfo);
            } else {
                this.loading = false;
            }
        }
    }
}
</script>

<style scoped lang="less">
.cropper-content {
    .cropper {
        width: auto;
        height: 300px;
    }
}
</style>
Copy the code

Conclusion:

The main clipping roles in cropper.vue are the Finish () method and convertBase64UrlToBlob(). Note that: This.$refs.cropper.getCropData() returns the clipped image as base64, and converts the base64 data into Blob objects. It stores the data sequence of the cropped image and then throws the processed address to the server.

Fixed set to false will limit the width and height of the clipping

The above is just my opinion.