前端图片裁剪上传实现方案
前端图片裁剪上传是常见的用户交互需求,涉及文件选择、图片预览、裁剪操作和上传处理等多个环节。以下是几种主流实现方式及其代码示例。
使用HTML5 Canvas实现基础裁剪
通过Canvas API可以实现基础的图片裁剪功能,适合轻量级需求。
<input type="file" id="uploader" accept="image/*">
<canvas id="canvas"></canvas>
<button id="crop-btn">裁剪并上传</button>
<script>
const uploader = document.getElementById('uploader');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let imageObj = null;
uploader.addEventListener('change', (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (event) => {
imageObj = new Image();
imageObj.src = event.target.result;
imageObj.onload = () => {
canvas.width = 300;
canvas.height = 300;
ctx.drawImage(imageObj, 0, 0, 300, 300);
};
};
reader.readAsDataURL(file);
});
document.getElementById('crop-btn').addEventListener('click', () => {
const croppedData = canvas.toDataURL('image/jpeg');
// 上传逻辑
fetch('/upload', {
method: 'POST',
body: JSON.stringify({ image: croppedData }),
headers: { 'Content-Type': 'application/json' }
});
});
</script>
使用Cropper.js专业裁剪库
Cropper.js提供了更完整的裁剪功能,包括拖拽、缩放、旋转等交互。
<link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.min.js"></script>
<div>
<input type="file" id="input">
<img id="image" style="max-width: 100%">
</div>
<script>
const input = document.getElementById('input');
const image = document.getElementById('image');
let cropper;
input.addEventListener('change', (e) => {
if (cropper) cropper.destroy();
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = (event) => {
image.src = event.target.result;
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 1
});
};
reader.readAsDataURL(file);
});
function uploadCroppedImage() {
cropper.getCroppedCanvas().toBlob((blob) => {
const formData = new FormData();
formData.append('file', blob, 'cropped.jpg');
fetch('/upload', {
method: 'POST',
body: formData
});
}, 'image/jpeg');
}
</script>
React实现方案(使用react-cropper)
对于React项目,可以使用react-cropper封装组件。
import React, { useRef, useState } from 'react';
import Cropper from 'react-cropper';
import 'cropperjs/dist/cropper.css';
function ImageUploader() {
const [image, setImage] = useState('');
const cropperRef = useRef(null);
const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = () => setImage(reader.result);
reader.readAsDataURL(file);
}
};
const handleCrop = () => {
const cropper = cropperRef.current?.cropper;
if (cropper) {
cropper.getCroppedCanvas().toBlob((blob) => {
const formData = new FormData();
formData.append('file', blob);
// 上传逻辑
});
}
};
return (
<div>
<input type="file" onChange={handleFileChange} />
<Cropper
ref={cropperRef}
src={image}
style={{ height: 400, width: '100%' }}
aspectRatio={1}
guides={true}
/>
<button onClick={handleCrop}>裁剪并上传</button>
</div>
);
}
性能优化与注意事项
- 限制上传文件大小:在文件选择时进行校验
if (file.size > 5 * 1024 * 1024) {
alert('文件大小不能超过5MB');
return;
}
- 压缩图片质量:减少上传体积
canvas.toBlob(callback, 'image/jpeg', 0.7); // 70%质量
- 显示上传进度
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (e) => {
const percent = Math.round((e.loaded / e.total) * 100);
console.log(`上传进度: ${percent}%`);
});
- 后端响应处理:建议返回CDN地址或文件存储路径
response.json().then(data => {
console.log('文件访问地址:', data.url);
});
以上方案可根据具体项目需求进行组合或调整,现代浏览器已普遍支持这些API,但需注意移动端兼容性和性能优化。
1056

被折叠的 条评论
为什么被折叠?



