vue实现图片裁剪
Vue 实现图片裁剪的方法
使用第三方库 vue-cropperjs
安装 vue-cropperjs 库:
npm install vue-cropperjs
在 Vue 组件中引入并使用:
<template>
<div>
<input type="file" @change="uploadImage" accept="image/*">
<vue-cropper
ref="cropper"
:src="imgSrc"
:aspect-ratio="16/9"
:auto-crop-area="0.8"
></vue-cropper>
<button @click="cropImage">裁剪图片</button>
<img :src="croppedImage" v-if="croppedImage">
</div>
</template>
<script>
import VueCropper from 'vue-cropperjs';
import 'cropperjs/dist/cropper.css';
export default {
components: {
VueCropper
},
data() {
return {
imgSrc: '',
croppedImage: ''
};
},
methods: {
uploadImage(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
this.imgSrc = event.target.result;
};
reader.readAsDataURL(file);
},
cropImage() {
this.$refs.cropper.getCroppedCanvas().toBlob((blob) => {
const reader = new FileReader();
reader.onload = (event) => {
this.croppedImage = event.target.result;
};
reader.readAsDataURL(blob);
});
}
}
};
</script>
使用 HTML5 Canvas 原生实现
创建自定义图片裁剪组件:
<template>
<div>
<input type="file" @change="handleFileChange" accept="image/*">
<div v-if="imageLoaded">
<canvas ref="canvas" @mousedown="startCrop" @mousemove="drawCrop" @mouseup="endCrop"></canvas>
<button @click="crop">裁剪</button>
<img :src="croppedImage" v-if="croppedImage">
</div>
</div>
</template>
<script>
export default {
data() {
return {
image: null,
imageLoaded: false,
canvas: null,
ctx: null,
isCropping: false,
startX: 0,
startY: 0,
endX: 0,
endY: 0,
croppedImage: ''
};
},
mounted() {
this.canvas = this.$refs.canvas;
this.ctx = this.canvas.getContext('2d');
},
methods: {
handleFileChange(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
this.image = new Image();
this.image.onload = () => {
this.canvas.width = this.image.width;
this.canvas.height = this.image.height;
this.ctx.drawImage(this.image, 0, 0);
this.imageLoaded = true;
};
this.image.src = event.target.result;
};
reader.readAsDataURL(file);
},
startCrop(e) {
this.isCropping = true;
const rect = this.canvas.getBoundingClientRect();
this.startX = e.clientX - rect.left;
this.startY = e.clientY - rect.top;
},
drawCrop(e) {
if (!this.isCropping) return;
const rect = this.canvas.getBoundingClientRect();
this.endX = e.clientX - rect.left;
this.endY = e.clientY - rect.top;
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.drawImage(this.image, 0, 0);
this.ctx.strokeStyle = 'red';
this.ctx.lineWidth = 2;
this.ctx.strokeRect(
this.startX,
this.startY,
this.endX - this.startX,
this.endY - this.startY
);
},
endCrop() {
this.isCropping = false;
},
crop() {
const width = this.endX - this.startX;
const height = this.endY - this.startY;
const cropCanvas = document.createElement('canvas');
cropCanvas.width = width;
cropCanvas.height = height;
const cropCtx = cropCanvas.getContext('2d');
cropCtx.drawImage(
this.canvas,
this.startX,
this.startY,
width,
height,
0,
0,
width,
height
);
this.croppedImage = cropCanvas.toDataURL('image/png');
}
}
};
</script>
注意事项
- 对于移动端支持,需要添加 touch 事件处理
- 考虑添加缩放和旋转功能时,需要更复杂的坐标变换计算
- 生产环境中建议使用成熟的第三方库以获得更好的兼容性和功能支持
- 大图片处理时需要考虑性能优化,可能需要使用 Web Worker
两种方法各有优缺点:vue-cropperjs 功能全面但依赖第三方库,原生实现更轻量但需要自行处理更多细节。根据项目需求选择合适方案。







