在现代Web应用中,图片处理是一个常见的需求。本文将介绍如何使用Vue.js结合Cropper.js实现一个简单的图片裁剪功能。以下是实现该功能的完整代码。
代码实现
<template><div class="c-copper-container" :class="{'wd260' : type == 'articlesubmit'}"><div class="c-copper-box"><div class="c-image-box"><img :src="copperImgUrl" id="image" alt="暂无图片"></div><div class="c-preview-box"><div class="img-preview"><div class="title">预览</div><div class="preview"><img :src="copperImgUrl" alt="暂无图片"></div></div><div class="img-upload-btn"><el-button icon="cs-format-image" size="mini" plain>上传图片</el-button><input type="file" accept="image/png,image/jpeg,image/jpg" id="imgFile" @change="getFile"></div></div></div><div class="c-btn-group"><el-button type="info" plain @click="cancel">取消</el-button><el-button type="primary" @click="getCropperImg">确定</el-button></div></div>
</template>
代码解析
-
<div class="c-copper-container" :class="{'wd260' : type == 'articlesubmit'}">
:- 定义了一个容器,并根据
type
属性动态添加wd260
类。
- 定义了一个容器,并根据
-
<div class="c-copper-box">
:- 包含图片裁剪和预览的主要布局。
-
<div class="c-image-box">
:- 裁剪图片显示区域。
-
<img :src="copperImgUrl" id="image" alt="暂无图片">
:- 绑定了一个图片标签,用于显示裁剪的图片。
-
<div class="c-preview-box">
:- 图片预览区域。
-
<div class="img-preview">
:- 包含预览标题和预览图片。
-
<el-button icon="cs-format-image" size="mini" plain>上传图片</el-button>
:- 上传图片按钮。
-
<input type="file" accept="image/png,image/jpeg,image/jpg" id="imgFile" @change="getFile">
:- 文件输入框,监听文件变化事件
getFile
。
- 文件输入框,监听文件变化事件
-
<el-button type="info" plain @click="cancel">取消</el-button>
:- 取消按钮,触发
cancel
方法。
- 取消按钮,触发
-
<el-button type="primary" @click="getCropperImg">确定</el-button>
:- 确定按钮,触发
getCropperImg
方法。
- 确定按钮,触发
JavaScript 部分
javascript"><script>import { dataURItoBlob } from '@/utils'export default {name: 'CropperImage',data () {return {copperImgUrl: '', // 被剪裁的图片地址option: {viewMode: 1, // 裁剪框只能图片内部移动dragMode: 'move', // 裁剪框只可以移动,不可以新建aspectRatio: 1, // 裁剪框比例preview: '.preview', // 预览的dom节点checkCrossOrigin: false, // 不检查跨域图像movable: false, // 设置图片可不移动rotatable: false, // 设置图片不可旋转scalable: false, // 设置图片不可缩放zoomable: false, // 设置图片不可放大zoomOnTouch: false, // 设置图片不可被拖动触摸放大toggleDragModeOnDblclick: true, // 点击两次时可以在“crop”和“move”之间切换拖拽模式minCropBoxWidth: '5', // 裁剪层最小宽度minCropBoxHeight: '5' // 裁剪层最小高度}}},props: {cropperOption: {type: Object,default: () => {return null}},fileSize: {type: Number,default: 0.8},fileType: {type: String,default: 'jpeg'},imageFile: {},sizeNum:{type: Number,default: 0},type:{type: String,default: ''}},watch: {imageFile (file) {this.fileHandle(file)}},methods: {initCropperModel () {if (this.cropperOption) {for (let key in this.option) {this.option[key] = this.cropperOption[key] || this.option[key]}}let $image = document.getElementById('image')this.cropper = new Cropper($image, this.option)},getFile (e) {let file = e.target.files[0]let _sizeNum = this.sizeNumif(_sizeNum){const isLtSize = file.size / 1024 / 1024 < _sizeNumif (!isLtSize) {this.$message({message: this.type == 'articlesubmit' ? `图片大小不能超过 ${_sizeNum}M!` : `图片大小不能超过 ${_sizeNum * 1000}kb!`,type: 'error'})e.target.value = ''return false}}this.fileHandle(file)},fileHandle (file) {if (!file) return if (!window.FileReader) return let vm = thislet reader = new FileReader()reader.readAsDataURL(file)reader.onloadend = function () {vm.copperImgUrl = this.resultvm.resetCropperImg()}},resetCropperImg () {this.cropper.reset()this.cropper.replace(this.copperImgUrl)},getCropperImg () {let canvas = this.cropper.getCroppedCanvas();if (this.fileType === 'image/png') {let ctx = canvas.getContext('2d');ctx.fillStyle = "rgba(0,0,0,0)"; ctx.fillRect(0, 0, canvas.width, canvas.height);}let newImageData = canvas.toDataURL('image/png');let blob = dataURItoBlob(newImageData);let formData = new FormData();formData.append('icon', blob);this.$emit('cropped', newImageData, formData);},cancel () {this.$emit('cancel')}},created () {this.fileHandle(this.imageFile)},mounted () {this.initCropperModel()},beforeDestroy () {this.copperImgUrl = ''this.cropper.destroy()}}
</script>
代码解析
-
data ()
:- 定义组件的数据属性,包括图片URL和裁剪器的配置项。
-
props
:- 定义父组件传入的属性,包括裁剪配置、文件大小和类型等。
-
watch
:- 监听
imageFile
的变化,当文件变化时调用fileHandle
方法。
- 监听
-
methods
:initCropperModel ()
:初始化 Cropper.js 实例。getFile (e)
:获取上传的文件并处理。fileHandle (file)
:处理上传的文件,将文件转换为Base64格式。resetCropperImg ()
:重置裁剪器的图片。getCropperImg ()
:获取裁剪后的图片,并将其转换为Blob格式。cancel ()
:取消操作。
-
created ()
:- 在组件创建时处理初始图片文件。
-
mounted ()
:- 在组件挂载时初始化裁剪器。
-
beforeDestroy ()
:- 在组件销毁前清理裁剪器实例。
样式部分
<style scoped lang="stylus" rel="stylesheet">.c-copper-container {width 450pxfont-size 12pxmargin-top 20px&.wd260{width 260px.img-upload-btn .el-button{padding 7px 5px}.c-image-box {width 188pxheight 188px& img {max-width 100%}>>> .cropper-bg{width 200px !important}}.c-preview-box {width 80px.img-preview {padding 5px 8pxheight 100px}.preview {width 60pxheight 60px}}}.c-copper-box {display flex}.c-image-box {width 250pxheight 250pxmargin-right 20pxbackground #868686& img {max-width 100%}}.c-preview-box {width 180pxtext-align center.img-preview {width 100%padding 10px 15pxheight 200pxbox-sizing border-boxborder 1px solid #e8e8e8background #fafafa}.title {padding-bottom 5px}.preview {width 148pxheight 148pxoverflow hiddenbackground-color #fffborder 1px solid #e8e8e8display inline-block}}.img-upload-btn {position relativemargin-top 18px&:hover .el-button {color #168FCAborder-color #168FCAtransition all .1s}& /deep/ i, & /deep/ span {display inline-blockvertical-align middle}.el-button {width 100%border-radius 0}#imgFile {position absolutewidth 100%height 100%top 0left 0opacity 0cursor pointer}}.c-btn-group {padding-top 20pxtext-align center.el-button {width 100px}}}
</style>
代码解析
-
定义了组件的样式,包括容器宽度、字体大小等。
-
使用了
scoped
属性,确保样式仅应用于当前组件。 -
采用了Stylus语法编写样式,提高了代码的可读性和易维护性。
总结
通过以上代码,我们实现了一个基于Vue.js和Cropper.js的图片裁剪组件,用户可以上传图片并进行裁剪操作,最终获取裁剪后的图片数据。这个组件可以方便地集成到Vue.js应用中,为用户提供了良好的图片处理体验。