react-image-crop
react-image-crop 是react响应式图片裁剪的一个工具包,能做到裁剪区域,裁剪宽高比限制等等。
npm地址:https://www.npmjs.com/package/react-image-crop
阅读前须知
版本的不同,在使用时有不同的表现,也可能造成使用失败。
本文中基于版本:8.6.2
安装
npm
npm install react-image-crop --save
CDN
<script src="https://unpkg.com/react-image-crop/dist/ReactCrop.min.js"></script>
注意,当使用<script>标签全局导入脚本时,请使用ReactCrop.Component访问组件。
使用
在使用得地方导入组件和样式模块
import ReactCrop from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';
// or scss;
import 'react-image-crop/lib/ReactCrop.scss'
组件使用
<ReactCrop
src={imageurl}
crop={crop}
ruleOfThirds
onImageLoaded={this.onImageLoaded}
onComplete={this.onCropComplete}
onChange={this.onCropChange}
/>
属性解释:
src:图片路径
crop:裁剪相关配置 参考地址:https://www.npmjs.com/package/react-image-crop#crop-required
ruleOfThirds:裁剪区域三分规则默认false;
ruleOfThirds为false时:
ruleOfThirds为true时(注意图中裁剪区域的九宫格):
onImageLoaded: 图片加载时的回调函数,返回image对象;
onComplete:裁剪区域调整大小、拖动、微调之后的回调,返回当前裁剪对象;
onChange:裁剪区域调整大小、拖动、微调时的回调,返回当前裁剪对象;官网中的提示:请注意,您必须实现此回调并更新您的裁剪状态,否则什么都不会改变!
更多属性参考
获取到的裁剪区域保存为图片
// 组件的onComplete事件
onCropComplete = crop => {
this.makeClientCrop(crop);
};
// 调用getCroppedImg函数获取裁剪图片信息
async makeClientCrop(crop) {
if (this.imageRef && crop.width && crop.height) {
const croppedImageUrl = await this.getCroppedImg(
this.imageRef,
crop,
'newFile.jpeg'
);
/*
* croppedImageUrl: {url,blob,crop}
* @url:图片文件对象的DOMString url
* @blob: 图片文件的类文件对象
* @crop: 裁剪参数
*/
}
// 裁剪区域转图片的处理
getCroppedImg(image, crop, fileName) {
const canvas = document.createElement('canvas');
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width = crop.width;
canvas.height = crop.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height
);
return new Promise((resolve, reject) => {
canvas.toBlob(blob => {
if (!blob) {
//reject(new Error('Canvas is empty'));
console.error('Canvas is empty');
return;
}
blob.name = fileName;
window.URL.revokeObjectURL(this.fileUrl);
this.fileUrl = window.URL.createObjectURL(blob);
resolve({url:this.fileUrl,blob,crop});
}, 'image/jpeg');
});
}
官方完整示例代码
import ReactDOM from "react-dom";
import React, { PureComponent } from "react";
import ReactCrop from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";
import "./App.css";
class App extends PureComponent {
state = {
src: null,
crop: {
unit: "%",
width: 30,
aspect: 16 / 9
}
};
onSelectFile = e => {
if (e.target.files && e.target.files.length > 0) {
const reader = new FileReader();
reader.addEventListener("load", () =>
this.setState({ src: reader.result })
);
reader.readAsDataURL(e.target.files[0]);
}
};
// If you setState the crop in here you should return false.
onImageLoaded = image => {
this.imageRef = image;
};
onCropComplete = crop => {
this.makeClientCrop(crop);
};
onCropChange = (crop, percentCrop) => {
// You could also use percentCrop:
// this.setState({ crop: percentCrop });
this.setState({ crop });
};
async makeClientCrop(crop) {
if (this.imageRef && crop.width && crop.height) {
const croppedImageUrl = await this.getCroppedImg(
this.imageRef,
crop,
"newFile.jpeg"
);
this.setState({ croppedImageUrl });
}
}
getCroppedImg(image, crop, fileName) {
const canvas = document.createElement("canvas");
const scaleX = image.naturalWidth / image.width;
const scaleY = image.naturalHeight / image.height;
canvas.width = crop.width;
canvas.height = crop.height;
const ctx = canvas.getContext("2d");
ctx.drawImage(
image,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height
);
return new Promise((resolve, reject) => {
canvas.toBlob(blob => {
if (!blob) {
//reject(new Error('Canvas is empty'));
console.error("Canvas is empty");
return;
}
blob.name = fileName;
window.URL.revokeObjectURL(this.fileUrl);
this.fileUrl = window.URL.createObjectURL(blob);
resolve(this.fileUrl);
}, "image/jpeg");
});
}
render() {
const { crop, croppedImageUrl, src } = this.state;
return (
<div className="App">
<div>
<input type="file" accept="image/*" onChange={this.onSelectFile} />
</div>
{src && (
<ReactCrop
src={src}
crop={crop}
ruleOfThirds
onImageLoaded={this.onImageLoaded}
onComplete={this.onCropComplete}
onChange={this.onCropChange}
/>
)}
{croppedImageUrl && (
<img alt="Crop" style={{ maxWidth: "100%" }} src={croppedImageUrl} />
)}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
在线编辑地址:https://codesandbox.io/s/react-image-crop-demo-with-classes-7jxc0?file=/src/index.js:0-2838