如何在React中将裁剪参数设置为原始图像?

时间:2018-03-15 15:00:30

标签: javascript image reactjs css3 ecmascript-6

我尝试在通过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");
}

现在,我无法获得正确的预览或新的图像文件对象,因此我可以使用它在模式中显示为预览,而不是使用它来上传它。我甚至没有获得正确的图像比例。有什么帮助吗?

这是图片: enter image description here

2 个答案:

答案 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

示例

&#13;
&#13;
drawImage(
    image,
    sx, sy, sw, sh,
    dx, dy, dw, dh
);
&#13;
&#13;
&#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;