如何使用Vue和Element-UI实现图片上传和剪裁功能

1. 前言

图片上传和剪裁功能在Web开发中非常常见,本文将介绍如何使用Vue和Element-UI实现这些功能。

2. 安装Element-UI

2.1 安装

首先,需要在项目中安装Element-UI。

npm i element-ui -S

2.2 引入样式

安装后,在项目的入口文件(如main.js)中引入Element-UI的CSS文件。

import 'element-ui/lib/theme-chalk/index.css';

3. 图片上传

使用Element-UI中的Upload组件可以轻松实现图片上传功能。

3.1 基本用法

首先需要在页面上引入Upload组件,并进行基本配置,如上传地址、上传方式等。

<template>

<div>

<el-upload

class="avatar-uploader"

:show-file-list="false"

:action="uploadUrl"

:on-success="handleSuccess"

:before-upload="beforeUpload">

<img v-if="imageUrl" :src="imageUrl" class="avatar">

<i v-else class="el-icon-plus avatar-uploader-icon"></i>

</el-upload>

</div>

</template>

<script>

export default {

data() {

return {

imageUrl: '',

uploadUrl: '/api/upload'

};

},

methods: {

handleSuccess(res, file) {

this.imageUrl = URL.createObjectURL(file.raw);

},

beforeUpload(file) {

// TODO: Check file size, format, etc.

}

}

};

</script>

在上面代码中,我们定义了一个Upload组件,并给它指定了上传接口地址(uploadUrl),图片上传成功后会通过handleSuccess方法处理,并把上传成功后的图片地址赋值给imageUrl变量,显示在页面上。我们还可以通过beforeUpload方法预处理上传的图片文件,在这个方法中可以检查图片的格式、大小等信息。

4. 图片剪裁

为了实现图片剪裁功能,我们需要引入一个第三方工具——Cropperjs(一个用于图片剪裁的JavaScript插件)。

4.1 安装Cropperjs

可以使用npm安装Cropperjs。

npm i cropperjs -S

4.2 剪裁工具组件

可以使用一个Cropper组件封装剪裁器并对其进行初始化、销毁等操作。首先在页面上引入Cropperjs和相关样式。

<template>

<div class="cropper-wrap">

<img :src="imageUrl" ref="image" />

</div>

</template>

<script>

import Cropper from 'cropperjs';

export default {

data() {

return {

cropper: null,

options: {}

};

},

mounted() {

// 初始化 Cropper.js

this.initCropper();

},

methods: {

initCropper() {

// 通过 ref 获取图片元素

const imageElement = this.$refs.image;

if (!imageElement.complete) {

setTimeout(() => this.initCropper(), 100);

return;

}

// 初始化 Cropper.js

this.cropper = new Cropper(imageElement, {

...this.options

});

},

// 销毁 Cropper.js

destroyCropper() {

this.cropper && this.cropper.destroy();

},

// 重置 Cropper.js

resetCropper() {

this.cropper && this.cropper.reset();

}

},

watch: {

imageUrl() {

this.destroyCropper();

this.resetCropper();

this.initCropper();

}

},

beforeDestroy() {

this.destroyCropper();

}

};

</script>

<style lang="scss">

.cropper-wrap {

width: 100%;

height: 100%;

display: flex;

align-items: center;

justify-content: center;

overflow: hidden;

img {

max-width: 100%;

max-height: 100%;

}

}

</style>

上面的代码中,我们定义了一个Cropper组件,通过引入Cropperjs和初始化操作(initCropper方法)使图片可被剪裁。在Cropper组件的mounted钩子中,我们通过 ref 获取到图片元素,通过判断图片是否加载完成来确定是否初始化Cropperjs。在Cropper组件中,我们定义了三个方法,分别是销毁Cropper(destroyCropper)、重置Cropper(resetCropper)和初始化Cropper(initCropper)。其中,重置Cropper是因为在修改图片地址后需要重新初始化Cropper,而销毁Cropper则是在组件销毁前释放文档流来解决内存泄漏问题。此外,我们也定义了一个变量(options),用于设置Cropperjs的相关配置。

5. 图片上传和剪裁的结合

将图片上传和剪裁结合起来,就可以实现完整的图片上传和剪裁功能。

5.1 组件封装

我们可以创建一个包含图片上传和剪裁组件的封装组件。

<template>

<div>

<!-- 图片上传 -->

<el-upload

:action="uploadUrl"

:limit="1"

:on-success="handleSuccess"

:show-file-list="false"

:before-upload="beforeUpload">

<img v-if="imageUrl" :src="imageUrl" class="image-preview" />

<i v-else class="el-icon-upload"></i>

</el-upload>

<!-- 图片剪裁 -->

<el-dialog

:visible.sync="dialogVisible"

:before-close="beforeCloseDialog"

:destroy-on-close="true"

:close-on-click-modal="false">

<template #title>

图片剪裁

</template>

<div class="cropper-dialog-wrap" v-loading="dialogLoading">

<cropper

:imageUrl="imageUrl"

ref="cropper"

:options="cropperOptions"

/>

</div>

<div slot="footer">

<el-button v-if="!dialogLoading" @click="handleCancel">取消</el-button>

<el-button

type="primary"

:loading="dialogLoading"

@click="handleUpload">

上传

</el-button>

</div>

</el-dialog>

</div>

</template>

<script>

import Cropper from './Cropper.vue';

export default {

components: {

Cropper

},

data() {

return {

imageUrl: '',

uploadUrl: '',

dialogVisible: false,

dialogLoading: false,

cropperOptions: {

}

};

},

methods: {

handleSuccess(res, file) {

this.imageUrl = URL.createObjectURL(file.raw);

this.dialogVisible = true;

},

beforeUpload(file) {

// TODO: Check file size, format, etc.

return true;

},

handleCancel() {

this.dialogVisible = false;

},

beforeCloseDialog(done) {

this.$confirm('确认关闭?')

.then(() => {

done();

})

.catch(() => {});

},

async handleUpload() {

this.dialogLoading = true;

try {

const canvas = await this.$refs.cropper.cropper.getCroppedCanvas();

const dataUrl = canvas.toDataURL();

// TODO: Upload cropped image

} catch (error) {

console.error(error);

} finally {

this.dialogLoading = false;

this.dialogVisible = false;

}

}

}

};

</script>

<style lang="scss">

.el-upload .el-icon-upload {

font-size: 28px;

line-height: 70px;

display: flex;

align-items: center;

justify-content: center;

border: 1px solid #d9d9d9;

}

.image-preview {

max-width: 100%;

max-height: 400px;

margin-bottom: 10px;

border: 1px solid #d9d9d9;

}

.cropper-dialog-wrap {

width: 100%;

height: 300px;

display: flex;

align-items: center;

justify-content: center;

overflow: hidden;

}

</style>

上面的代码中,我们将图片上传和剪裁组件结合起来封装成一个组件。在图片上传成功后,弹出剪裁框(dialogVisible为true),用户对图片进行剪裁后,可点击“上传”按钮进行图片上传(handleUpload方法)。

6. 总结

本文通过介绍使用Vue和Element-UI实现图片上传和剪裁功能的方法来实现一个简单的图片上传剪裁组件。以上仅是简单的实现方式,实际中还需要根据需求进行相应的修改和添加。