vue專案新增圖片裁剪元件

帥燊發表於2020-12-16

vue專案新增圖片裁剪元件
功能如下圖所示:
在這裡插入圖片描述

1,安裝命令如下

npm i vue-cropper --save

2,呼叫元件,引入vue-cropper

import { VueCropper } from “vue-cropper”;

3,封裝元件程式碼如下:cropper.vue

<template>
  <div class="cropper_model">
    <el-dialog
      title="圖片剪裁"
      width="800px"
      class="cropper_model_dlg"
      :visible.sync="dialogVisible"
      append-to-body
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <div class="cropper_content">
        <div class="cropper" style="text-align: center;">
          <vueCropper
            ref="cropper"
            :img="options.img"
            :outputSize="options.outputSize"
            :outputType="options.outputType"
            :info="options.info"
            :canScale="options.canScale"
            :autoCrop="options.autoCrop"
            :autoCropWidth="options.autoCropWidth"
            :autoCropHeight="options.autoCropHeight"
            :fixed="options.fixed"
            :fixedBox="options.fixedBox"
            :fixedNumber="options.fixedNumber"
            @realTime="previewImg"
          >
          </vueCropper>
          <div class="cropper_btns">
            <el-button type="primary" @click="goUpload" size="mini">
              重新上傳
            </el-button>
            <el-button
              @click="rotateLeft"
              icon="el-icon-refresh-left"
              size="mini"
              title="左旋轉"
            >
            </el-button>
            <el-button
              @click="rotateRight"
              icon="el-icon-refresh-right"
              size="mini"
              title="右旋轉"
            >
            </el-button>
            <el-button @click="changeScale(1)" size="mini" title="放大">
              +
            </el-button>
            <el-button @click="changeScale(-1)" size="mini" title="縮小">
              -
            </el-button>
          </div>
        </div>
        <div class="cropper_right">
          <h3>預覽</h3>
          <!-- 預覽 -->
          <div
            class="cropper_preview"
            :style="{
              width: preview.w + 'px',
              height: preview.h + 'px',
              overflow: 'hidden',
              margin: '5px'
            }"
          >
            <div :style="preview.div">
              <img :src="preview.url" :style="preview.img" alt="" />
            </div>
          </div>
          <div style="margin-top: 100px;">
            <el-button type="primary" @click="uploadImg" :loading="loading">
              確定上傳
            </el-button>
          </div>
        </div>
      </div>
      <!-- <div slot="footer" class="dialog-footer">
        <el-button @click="downLoad('blob')">下載</el-button>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="uploadImg" :loading="loading">
          確認
        </el-button>
      </div> -->
    </el-dialog>
  </div>
</template>

<script>
import { VueCropper } from "vue-cropper";
export default {
  components: { VueCropper },
  data() {
    return {
      dialogVisible: false,
      loading: false,
      options: {
        img: "", // 裁剪圖片的地址
        outputSize: 1, // 裁剪生成圖片的質量
        outputType: "png", // 裁剪生成圖片的格式
        info: true, // 裁剪框的大小資訊
        canScale: true, // 圖片是否允許滾動縮放
        autoCrop: true, // 是否預設生成截圖狂
        autoCropWidth: 100, // 預設生成截圖框寬度
        autoCropHeight: 100, // 預設生成截圖框高度
        fixed: true, // 是否開啟截圖框寬高固定比例
        fixedNumber: [1, 1], // 截圖框的寬高比例
        full: true, // 是否輸出原圖比例的截圖
        fixedBox: true, // 固定截圖框大小 不允許改變
        canMove: true, // 上傳圖片是否可以移動
        canMoveBox: true, // 截圖框能否拖動
        original: true, // 上傳圖片按照原始比例渲染
        centerBox: false, // 截圖框是否被限制在圖片裡面
        high: false, // 是否按照裝置的dpr輸出等比例圖片
        infoTrue: true, // true為展示真實輸出圖片寬高false展示看到的截圖框寬高
        maximgSize: 100, // 限制圖片最大寬度和高度
        enlarge: 1, // 圖片根據截圖框輸出比例倍數
        mode: "contain" // 圖片預設渲染方式(contain, cover, 100px, 100% auto)
      },
      preview: {}
    };
  },
  methods: {
    open(data) {
      this.options.img = window.URL.createObjectURL(data);
      this.dialogVisible = true;
    },
    close(){
      this.dialogVisible = false;
    },
    // base64轉圖片檔案
    dataURLtoFile(dataurl, filename) {
      let arr = dataurl.split(",");
      let mime = arr[0].match(/:(.*?);/)[1];
      let bstr = atob(arr[1]);
      let len = bstr.length;
      let u8arr = new Uint8Array(len);
      while (len--) {
        u8arr[len] = bstr.charCodeAt(len);
      }
      return new File([u8arr], filename, { type: mime });
    },
    downLoad(type) {
      event.preventDefault();
      const aLink = document.createElement("a");
      if (type === "blob") {
        this.$refs.cropper.getCropBlob(data => {
          let downImg = window.URL.createObjectURL(data);
          aLink.download = "photo.png";
          aLink.href = downImg;
          aLink.click();
        });
      } else {
        this.$refs.cropper.getCropData(data => {
          let file = this.dataURLtoFile(data, "test");
          aLink.href = file;
          aLink.click();
        });
      }
    },
    // 左旋轉
    rotateLeft() {
      this.$refs.cropper.rotateLeft();
    },
    // 右旋轉
    rotateRight() {
      this.$refs.cropper.rotateRight();
    },
    // 放大縮小
    changeScale(num) {
      num = num || 1;
      this.$refs.cropper.changeScale(num);
    },
    // 實時預覽
    previewImg(data) {
      this.preview = data;
    },
    goUpload() {
      this.$emit("upAgain");
    },
    // 上傳圖片
    uploadImg() {
      let self = this;
      self.loading = true;
      this.$refs.cropper.getCropData(data => {
        let file = this.dataURLtoFile(data, "photo.png");
        // 生成檔案型別
        self.loading = false;
        this.$emit("getFile",file)
      });
    },
    //自定義上傳,裁剪後呼叫
  }
};
</script>

<style lang="less" scoped>
.cropper_model_dlg {
  .cropper_content {
    margin: 0 auto;
    width: 700px;
    height: 450px;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
  }
  .cropper {
    width: 400px;
    height: 400px;
    background: yellow;
  }
  .cropper_right {
    width: 300px;
    text-align: center;
  }
  .cropper_preview {
    margin: 0 auto;
    display: inline-block;
    border: 1px solid #ddd;
  }
  .cropper_btns {
    margin-top: 20px;
  }
}
</style>

4,在其他vue元件使用,引用cropper.vue

 import MyCropper from "./cropper.vue"

export default裡面新增

 components:{MyCropper},

html中引入

 <my-cropper ref="myCropper" @getFile="getFile" @upAgain="upAgain"></my-cropper>

對應的js方法程式碼

 upAgain(){
                this.$refs['upload'].$refs["upload-inner"].handleClick();
            },

getFile(file){
                const formData = new FormData();
                formData.append("file",file)
                uploadSelfCompanyLogo(formData).then(res =>{
                    if (res.code === 0) {
                        this.companyInfo.logo = res.filename;
                        this.companyInfo.imageUrl = res.url;
                        this.imageUrl = res.url;
                        //上傳成功後,關閉彈框元件
                        // this.handleCrop(file);
                        this.$refs.myCropper.close()

                    } else {
                        this.$message.error('上傳出錯');
                    }
                })
               // this.$refs.upload.submit();
            },

注意:以上程式碼並不完整,下篇文章會分享 裁剪元件和elementUI元件中的el-upload的結合使用方法

相關文章