我尝试在通过API上传图像之前裁剪图像。我正在展示一个模态(Dialog
)来执行此操作,并使用此库react-image-crop来实现此目的。
以下是代码段:
showCropImageModal() {
const actions = [
<FlatButton
label="Cancel"
primary={true}
onClick={this.handleCancel}
/>,
<FlatButton
label="Crop"
primary={true}
keyboardFocused={true}
onClick={this.handleCropClose}
/>,
];
if (this.state.showImageCropper) {
return (
<div>
<Dialog
title="Crop the image"
actions={actions}
modal={true}
open={this.state.showImageCropper}
autoScrollBodyContent={true}
>
<ReactCrop
src={this.state.selectedImageURL}
crop={this.state.crop}
onComplete={(crop, pixel) => {console.log(crop, pixel)}}
onChange={(crop) => { console.log(crop); this.setState({crop}); }}
/>
</Dialog>
</div>
);
}
}
On&#34; Crop&#34;我正在使用handleCropClose
函数处理它:
handleCropClose(){
let {selectedFile, crop} = this.state
const croppedImg = this.getCroppedImg(selectedFile, crop.width, crop.height, crop.x, crop.y, 2);
console.log(croppedImg)
this.setState({showImageCropper: false})
}
这是getCroppedImg
代码:
getCroppedImg(imgObj, newWidth, newHeight, startX, startY, ratio) {
/* the parameters: - the image element - the new width - the new height - the x point we start taking pixels - the y point we start taking pixels - the ratio */
// Set up canvas for thumbnail
console.log(imgObj)
var img = new Image();
img.src = this.state.selectedImageURL;
var tnCanvas = this.refs.canvas;
tnCanvas.width = newWidth;
tnCanvas.height = newHeight;
tnCanvas.getContext('2d').drawImage(img, startX, startY, newWidth, newHeight);
return tnCanvas.toDataURL("image/png");
}
现在,我无法获得正确的预览或新的图像文件对象,因此我可以使用它在模式中显示为预览,而不是使用它来上传它。我甚至没有获得正确的图像比例。有什么帮助吗?
答案 0 :(得分:3)
解决方案:
首先,使用像素坐标:
- 更改:subClasses[2]
- 到onChange={(crop) => { console.log(crop); this.setState({crop}); }}
。
onChange={(crop, pixelCrop) => { console.log(crop); this.setState({crop, pixelCrop}); }}
使用this.state.pixelCrop
代替this.state.crop
。
然后,更新getCroppedImg
以使用Promise异步获取图像并裁剪它。
getCroppedImg
解释:
您缺少getCroppedImg(imgObj, newWidth, newHeight, startX, startY, ratio) {
/* the parameters: - the image element - the new width - the new height - the x point we start taking pixels - the y point we start taking pixels - the ratio */
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = resolve;
img.onerror = reject;
img.src = this.state.selectedImageURL;
}).then(img => {
// Set up canvas for thumbnail
var tnCanvas = this.refs.canvas;
tnCanvas.width = newWidth;
tnCanvas.height = newHeight;
tnCanvas
.getContext('2d')
.drawImage(
img,
startX, startY, newWidth, newHeight,
0, 0, newWidth, newHeight
);
return tnCanvas.toDataURL("image/png");
});
}
的参数。您要求画布在位置drawImage
处绘制图像并将其缩放为(startX, startY)
。
要裁剪您需要的图片additional parameters:
(newWidth, newHeight)
其中:
示例:
drawImage(
image,
sx, sy, sw, sh,
dx, dy, dw, dh
);
&#13;
答案 1 :(得分:1)
react-image-crop
使用百分比进行缩放,请务必进行计算。还要确保在动态创建新对象图像时渲染虚拟dom。
在这里,试试这个:
import React, { Component } from 'react';
import ReactCrop, { makeAspectCrop } from 'react-image-crop';
import { FlatButton, Dialog } from 'material-ui';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import sample from './sample.png';
import 'react-image-crop/dist/ReactCrop.css';
class App extends Component {
state = {
showImageCropper: false,
selectedImageURL: sample,
crop: {
x: 0,
y: 0,
// aspect: 16 / 9,
},
selectedFile: null,
croppedImage: sample
};
showCropImageModal() {
const actions = [
<FlatButton
label="Cancel"
primary={true}
onClick={this.handleCancel}
/>,
<FlatButton
label="Crop"
primary={true}
keyboardFocused={true}
onClick={this.handleCropClose}
/>,
];
if (this.state.showImageCropper) {
return (
<div>
<Dialog
title="Crop the image"
actions={actions}
modal={true}
open={this.state.showImageCropper}
autoScrollBodyContent={true}
>
<ReactCrop
src={this.state.selectedImageURL}
crop={this.state.crop}
// onImageLoaded={this.onImageLoaded}
onComplete={this.onCropComplete}
onChange={this.onCropChange}
/>
</Dialog>
</div>
);
}
}
onCropComplete = (crop, pixels) => {
}
onCropChange = (crop) => {
this.setState({ crop });
}
// onImageLoaded = (image) => {
// this.setState({
// crop: makeAspectCrop({
// x: 0,
// y: 0,
// // aspect: 10 / 4,
// // width: 50,
// }, image.naturalWidth / image.naturalHeight),
// image,
// });
// }
handleCancel = () => {
this.setState({ showImageCropper: false });
}
handleCropClose = () => {
let { crop } = this.state;
// console.log("selectedFile", selectedFile);
// console.log("crop",crop);
const croppedImg = this.getCroppedImg(this.refImageCrop, crop);
this.setState({ showImageCropper: false, croppedImage: croppedImg })
}
getCroppedImg(srcImage,pixelCrop) {
/* the parameters: - the image element - the new width - the new height - the x point we start taking pixels - the y point we start taking pixels - the ratio */
// Set up canvas for thumbnail
// console.log(imgObj);
// let img = new Image();
// img.src = this.state.selectedImageURL;
// let tempCanvas = document.createElement('canvas');
// let tnCanvas = tempCanvas;
// tnCanvas.width = newWidth;
// tnCanvas.height = newHeight;
// tnCanvas.getContext('2d').drawImage(img, startX, startY, newWidth, newHeight);
// return tnCanvas;
let img = new Image();
img.src = this.state.selectedImageURL;
const targetX = srcImage.width * pixelCrop.x / 100;
const targetY = srcImage.height * pixelCrop.y / 100;
const targetWidth = srcImage.width * pixelCrop.width / 100;
const targetHeight = srcImage.height * pixelCrop.height / 100;
const canvas = document.createElement('canvas');
canvas.width = targetWidth;
canvas.height = targetHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(
img,
targetX,
targetY,
targetWidth,
targetHeight,
0,
0,
targetWidth,
targetHeight
);
return canvas.toDataURL('image/jpeg');
}
handleOpen = () => {
this.setState({ showImageCropper: true });
}
render() {
return (
<MuiThemeProvider>
<div className="App">
{ this.showCropImageModal() }
<img src={this.state.selectedImageURL} style={{display: "none"}} ref={(img) => {this.refImageCrop = img}} alt="" />
<img src={this.state.croppedImage} alt="" />
<FlatButton
label="Open popup"
primary={true}
onClick={this.handleOpen}
/>
</div>
</MuiThemeProvider>
);
}
}
export default App;