vue2圖片裁剪(vue-cropper外掛)

larry-wang發表於2024-11-06

文件地址:https://github.com/xyxiao001/vue-cropper

安裝:

npm install vue-cropper

子元件

<template>
  <el-dialog
    title="裁剪頭像"
    :visible.sync="dialogVisible"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    width="600px"
    append-to-body
    @close="closeDialog"
  >
    <div class="avatar-container">
      <!-- 待上傳圖片 -->
      <div v-show="!options.img">
        <el-upload
          ref="upload"
          class="upload"
          action=""
          :on-change="upload"
          accept="image/png, image/jpeg, image/jpg"
          :show-file-list="false"
          :auto-upload="false"
        >
          <el-button slot="trigger" ref="uploadBtn" size="small" type="primary">
            選擇圖片
          </el-button>
        </el-upload>
        <div>支援jpg、png格式的圖片,大小不超過5M</div>
      </div>
      <!-- 已上傳圖片 -->
      <div v-show="options.img" class="avatar-crop">
        <vueCropper
          v-if="dialogVisible"
          ref="cropper"
          class="crop-box"
          :img="options.img"
          :auto-crop="options.autoCrop"
          :fixed-box="options.fixedBox"
          :can-move-box="options.canMoveBox"
          :auto-crop-width="options.autoCropWidth"
          :auto-crop-height="options.autoCropHeight"
          :center-box="options.centerBox"
          :fixed="options.fixed"
          :fixed-number="options.fixedNumber"
          :can-move="options.canMove"
          :can-scale="options.canScale"
        />
      </div>
    </div>
    <span slot="footer" class="dialog-footer">
      <div class="reupload" @click="reupload">
        <span v-show="options.img">重新上傳</span>
      </div>
      <div>
        <el-button @click="closeDialog">取 消</el-button>
        <el-button type="primary" @click="getCrop">確 定</el-button>
      </div>
    </span>
    <!-- </el-dialog> -->
  </el-dialog>
</template>
<script>
import { VueCropper } from 'vue-cropper'
export default {
  name: 'AvatarCropper',
  components: {
    VueCropper
  },
  props: {
    dialogVisible: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      // vueCropper元件 裁剪配置資訊
      options: {
        name: '',
        img: '', // 原圖檔案
        autoCrop: true, // 預設生成截圖框
        fixedBox: false, // 固定截圖框大小
        canMoveBox: true, // 截圖框可以拖動
        autoCropWidth: 200, // 截圖框寬度
        autoCropHeight: 200, // 截圖框高度
        fixed: false, // 截圖框寬高固定比例
        fixedNumber: [1, 1], // 截圖框的寬高比例
        centerBox: true, // 截圖框被限制在圖片裡面
        canMove: false, // 上傳圖片不允許拖動
        canScale: true // 上傳圖片不允許滾輪縮放
      }
    }
  },

  methods: {
    // 讀取原圖
    upload(file) {
      const isIMAGE = file.raw.type === 'image/jpeg' || file.raw.type === 'image/png'
      const isLt5M = file.raw.size / 1024 / 1024 < 5
      if (!isIMAGE) {
        this.$message({
          showClose: true,
          message: '請選擇 jpg、png 格式的圖片',
          type: 'warning'
        })
        return false
      }
      if (!isLt5M) {
        this.$message({
          showClose: true,
          message: '圖片大小不能超過 5MB',
          type: 'warning'
        })
        return false
      }
      const reader = new FileReader()
      reader.readAsDataURL(file.raw)
      reader.onload = e => {
        this.options.name = file.name
        this.options.img = e.target.result // base64
      }
    },
    // 獲取截圖資訊
    getCrop() {
      // 獲取截圖的 blob 資料
      this.$refs.cropper.getCropBlob((data) => {
        this.$emit('closeAvatarDialog', data, this.options.name)
        this.closeDialog()
      })
    },
    // 重新上傳
    reupload() {
      this.$refs.uploadBtn.$el.click()
    },
    // 關閉彈框
    closeDialog() {
      this.$emit('update:dialogVisible', false)
      this.options.img = ''
    }
  }
}
</script>

<style lang="scss" scoped>
.dialog-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 14px;
  .reupload {
    color: #409eff;
    cursor: pointer;
  }
}
.avatar-container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 560px;
  height: 400px;
  background-color: #f0f2f5;
  margin-right: 10px;
  border-radius: 4px;
  .upload {
    text-align: center;
    margin-bottom: 24px;
  }
  .avatar-crop {
    width: 560px;
    height: 400px;
    position: relative;
    .crop-box {
      width: 100%;
      height: 100%;
      border-radius: 4px;
      overflow: hidden;
    }
  }
}
</style>

父元件

<template>
  <div>
    <el-button @click="dialogVisible = true">上傳頭像</el-button>
    <avatar-cropper :dialogVisible.sync="dialogVisible" @closeAvatarDialog="closeAvatarDialog"></avatar-cropper>
  </div>
</template>

<script>
  import avatarCropper from '@/components/avatarCropper'
  export default {
    components: {
      avatarCropper
    },
    data() {
      return {
        dialogVisible: false
      }
    },
    methods: {
      closeAvatarDialog(data) {
        console.log(data)
        this.dialogVisible = false
      }
    }
  }
</script>

相關文章