前端Vue

【Vue】插件:九、vue-cropper 实现图片裁剪功能

2020-01-02  本文已影响0人  smartdream

1. 安装

官方参考文档

npm i vue-cropper

2. 使用

2.1 单独封装插件

|-src
|-|-plugins
|-|-|-vue-croppper.js

import Vue from 'vue';
import VueCropper from 'vue-cropper';

Vue.use(VueCropper);

2.2 main.js中

import './plugins/vue-cropper';// 图片裁剪插件

3 封装组件为by-cropper

3.1 template

/* 图片裁剪 */
<template>
    <div class="vue-cropper-box">
        <div class="vue-cropper-header">
            <p class="title">图片裁剪</p>
            <i type="primary" class="el-icon-close" @click="close()"></i>
        </div>
        <div class="vue-cropper-operate">
            <button class="basicButton" @click="cropperChangeScale(1)">放大</button>
            <button class="basicButton" @click="cropperChangeScale(-1)">缩小</button>
            <button class="basicButton" @click="cropperRotateLeft">左旋转</button>
            <button class="basicButton" @click="cropperRotateRight">右旋转</button>
            <button class="basicButton" @click="cropperDown('blob')">下载</button>
            <button class="basicButton" @click="cropperFinish">确定裁剪</button>
        </div>
        <div class="vue-cropper-content">
            <vueCropper
                ref="cropper"
                :img="cropperOption.img"
                :outputSize="cropperOption.outputSize"
                :outputType="cropperOption.outputType"
                :info="cropperOption.info"
                :full="cropperOption.full"
                :canMove="cropperOption.canMoveBox"
                :canMoveBox="cropperOption.canMoveBox"
                :original="cropperOption.original"
                :canScale="cropperOption.canScale"
                :autoCrop="cropperOption.autoCrop"
                :autoCropWidth="cropperOption.autoCropWidth"
                :autoCropHeight="cropperOption.autoCropHeight"
                :fixed="cropperOption.fixed"
                :fixedNumber="cropperOption.fixedNumber"
                @realTime="realTime"
                @imgLoad="imgLoad"
            ></vueCropper>
        </div>
    </div>
</template>

3.2 script

<script>
export default {
    name: 'by-cropper',
    components: {},
    inject: ['reload'],
    filters: {},
    props: {
        file: {
            default: () => {},
            required: true
        },
        cropperOption: {
            default: () => ({
                img: '', // 裁剪图片的地址
                info: true, // 裁剪框的大小信息
                outputSize: 1, // 裁剪生成图片的质量
                full: false, // 输出原图比例截图 props名full
                outputType: 'jpeg', // 裁剪生成图片的格式
                canMove: true, // 能否拖动图片
                original: false, // 上传图片是否显示原始宽高
                canMoveBox: true, // 能否拖动截图框
                canScale: false, // 图片是否允许滚轮缩放
                autoCrop: true, // 是否默认生成截图框
                autoCropWidth: 400, // 默认生成截图框宽度
                autoCropHeight: 300, // 默认生成截图框高度
                fixedBox: false, // 截图框固定大小
                fixed: true, // 是否开启截图框宽高固定比例
                fixedNumber: [4, 3] // 截图框的宽高比例
            })
        }
    },
    data() {
        return {
        };
    },
    computed: {
        // computeFunction() {
        //     return value;
        // }
    },
    watch: {
    },
    created() {
        // this.init();
    },
    mounted() {
        // this.init();
    },
    methods: {

        // ---------------图片裁剪功能-开始---------------
        cropperChangeScale(num) {
            num = num || 1;
            this.$refs.cropper.changeScale(num);
        },

        // 左旋转
        cropperRotateLeft() {
            this.$refs.cropper.rotateLeft();
        },

        // 右旋转
        cropperRotateRight() {
            this.$refs.cropper.rotateRight();
        },

        // 下载图片
        cropperDown(type) {
            console.log('down');
            let aLink = document.createElement('a');
            aLink.download = 'author-img';
            if (type === 'blob') {
                this.$refs.cropper.getCropBlob(data => {
                    this.downImg = window.URL.createObjectURL(data);
                    aLink.href = window.URL.createObjectURL(data);
                    aLink.click();
                });
            } else {
                this.$refs.cropper.getCropData(data => {
                    this.downImg = data;
                    aLink.href = data;
                    aLink.click();
                });
            }
        },

        // 确定裁剪
        cropperFinish(type) {
            if (type === 'Blob') {
                this.$refs.cropper.getCropBlob((data) => {
                    let file = data;
                    file.name = this.file.name;
                    this.$emit('cropperFinish', file, data);
                });

            } else {
                this.$refs.cropper.getCropData(data => {

                    // 将剪裁后base64的图片转化为file格式
                    let file = this.convertBase64UrlToBlob(data);
                    file.name = this.file.name;

                    this.$emit('cropperFinish', file, data);
                });
            }

        },

        // 将base64的图片转换为file文件
        convertBase64UrlToBlob(urlData) {
            let bytes = window.atob(urlData.split(',')[1]); // 去掉url的头,并转换为byte
            // 转化为base64
            // reader.readAsDataURL(file)
            // 转化为blob
            // 处理异常,将ascii码小于0的转换为大于0
            let ab = new ArrayBuffer(bytes.length);
            let ia = new Uint8Array(ab);
            for (let i = 0; i < bytes.length; i++) {
                ia[i] = bytes.charCodeAt(i);
            }
            return new Blob([ab], { type: 'image/jpeg' });
        },

        // 实时预览函数
        realTime(data) {
            // console.log('realTime');
        },

        // 图片已加载
        imgLoad(msg) {
            // console.log('imgLoad');
            // console.log(msg);
        },

        close() {
            this.$emit('close');
        }

    }
};
</script>

3.3 style 样式仅供参考

<style lang="less" scoped>
// 基础按钮
.basicButton {
  font-size: @font-size-m;
  padding: 0 0.1rem;
  line-height: 0.4rem;
  border: none;
  border-radius: @border-radius-middle;
  color: #fff;
  background: @base-color-blue;

  &:not(:last-child) {
    margin-right: 0.2rem;
  }

  &.disabled {
    opacity: 0.5;
  }

  &.cancel{
    background: @base-color-grey;
  }

  &.warning {
    background: @base-color-red;
  }

  &.black {
    background-color: @base-color-black;
  }
}
/* 图片裁剪工具 */
.vue-cropper-box{
  z-index: 3001;
  position: absolute;
  top: 0;
  width: 100%;
  height: 95%;
  background: #fff;  

  .vue-cropper-operate{
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.2rem;
  }

  .vue-cropper-content{
    width: 100%;
    height:calc(100% - 1rem);
    position: relative;
    overflow-y: auto;

    .vue-cropper{
      position: absolute;
    }
  }
}
</style>

4. 使用组件

4.1 template片段

<div v-if="isShowCropper">
    <by-cropper
        :cropperOption="cropperOption"
        :file="cropperFile"
        @cropperFinish="cropperFinish"
        @close="()=>{isShowCropper=false}"
        ></by-cropper>
</div>

4.2 script片段

vuex 中的上传接口,接口如何写可以参考文章【Vue教程】Vue Cli3项目结构优化【Vue教程】vuex、axios请求接口的几种方式

import ByCropper from '@/components/common/ByCropper';

export default {
    data() {
        return {
            /* vue-cropper 配置信息 */
            isShowCropper: false, // 是否显示-图片裁剪-弹窗
            cropperFile: {}, // 当前待裁剪图片的文件信息
            cropperOption: {
                img: '', // 裁剪图片的地址
                info: true, // 裁剪框的大小信息
                outputSize: 1, // 裁剪生成图片的质量
                full: false, // 输出原图比例截图 props名full
                outputType: 'jpeg', // 裁剪生成图片的格式
                canMove: true, // 能否拖动图片
                original: false, // 上传图片是否显示原始宽高
                canMoveBox: true, // 能否拖动截图框
                canScale: false, // 图片是否允许滚轮缩放
                autoCrop: true, // 是否默认生成截图框
                autoCropWidth: 400, // 默认生成截图框宽度
                autoCropHeight: 300, // 默认生成截图框高度
                fixedBox: false, // 截图框固定大小
                fixed: true, // 是否开启截图框宽高固定比例
                fixedNumber: [4, 3] // 截图框的宽高比例
            },
            methods:{
                // 以下方法可以根据 封装组件 this.$emit('cropperFinish', file, data); 中获取的 file data 自定义进行处理
                // 获取到文件时,进行如下处理
                handleFile(file){
                    this.cropperFile = file;
                    this.cropperOption.img = file.src;
                    this.isShowCropper = true;
                },
                // 确定裁剪
                cropperFinish(file) {
                    // 请求接口-上传文件
                    this.postUploadFile(file);
                },
                // 文件上传-接口-上传文件
                postUploadFile(file) {
                    console.log('PostUploadFile>', file);
                    let formData = new FormData();
                    formData.append('file', file, file.name);
                    // vuex 中的上传接口,接口如何写可以参考文章[杀杀杀]()
                    this.uploadFileCase(formData).then(res => {
                    console.log('uploadFileCase>', file);
                    if (res.code === 1) {
                    // 自定义操作
                    // this.fileList.push({
                        // name: file.name,
                        // src: file.src,
                       //  filePath: res.data,
                       //  file: file
                    // });
                    // this.ruleForm.imgPath = res.data;
                    // this.ruleForm.file = file;

                    this.isShowCropper = false;
                    this.cropperOption.img = null;
                    this.cropperFile = {};
                    }
                });
              },
            },
        }
    }
}

参考文档网址:
一个优雅的图片裁剪插件:vue-cropper
Vue项目图片剪切上传——vue-cropper的使用
vue使用vue-cropper实现裁剪、上传、下载功能

上一篇下一篇

猜你喜欢

热点阅读