【问题标题】:How to set crop parameters to original image in React?如何在 React 中将裁剪参数设置为原始图像?
【发布时间】:2018-08-24 11:06:35
【问题描述】:

我正在尝试在通过 API 上传图像之前对其进行裁剪。我正在展示一个模式 (Dialog) 来执行此操作,并使用此库 react-image-crop 来实现此目的。

这里是sn-p的代码:

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>
        );
    }
}

关于“裁剪”操作,我使用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");
}

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

图片如下:

【问题讨论】:

  • 嘿,抱歉,我觉得这个问题有点不清楚——而不是寻求“任何帮助?”,你在寻求什么帮助?
  • 我认为我想要什么已经很清楚了。请再看看。

标签: javascript image reactjs css ecmascript-6


【解决方案1】:

解决方案

首先,使用像素坐标: - 更改:onChange={(crop) =&gt; { console.log(crop); this.setState({crop}); }} - 到onChange={(crop, pixelCrop) =&gt; { console.log(crop); this.setState({crop, pixelCrop}); }}

使用this.state.pixelCrop 代替this.state.crop 代替getCroppedImg

然后,更新getCroppedImg 以使用 Promise 异步获取图像并对其进行裁剪。

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) 绘制图像并将其缩放到(newWidth, newHeight)

要裁剪您需要的图像additional parameters

drawImage(
    image,
    sx, sy, sw, sh,
    dx, dy, dw, dh
);

地点:

示例

const img = new Image()
const canvas = document.createElement('canvas')

img.src = 'https://cmeimg-a.akamaihd.net/640/clsd/getty/991dda07ecb947f1834bf1aa89153cf6'

const newWidth = 200
const newHeight = 200

const startX = 200
const startY = 100

img.onload = () => {
    canvas.width = newWidth;
    canvas.height = newHeight;
    canvas.getContext('2d').drawImage(img, startX, startY, newWidth, newHeight, 0, 0, newWidth, newHeight);
}


document.body.appendChild(canvas)
document.body.appendChild(img)

【讨论】:

  • 我尝试了你的 getCroppedImg 但它仍然无法正常工作,因为它确实裁剪了一些东西,但不是我需要的并且尺寸正确。你能用同样的方法来检查它是否有效吗?
  • 我尝试了代码,似乎它没有裁剪我选择的图像。可运行的代码不是我尝试的,我尝试了您在解决方案中提到的 getCroppedImg 函数。
  • 很难完全重现您的代码,如果您使用imgObj 而不是img 是否有效?否则您能否提供crop 的内容,以便我们查看它是否使用了正确的坐标空间?
  • 高度:33.33333333333333 宽度:57.272727272727266 x:24.261363636363637 y:25.333333333333332
  • height: 33.33333333333333 ​ width: 57.272727272727266 ​ x: 24.261363636363637 ​y: 25.333333333333332 这里是crop的内容。
【解决方案2】:

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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 2015-07-08
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    相关资源
    最近更新 更多