handle of cropper(upper left) in React-image-crop is not working correctly in terms of selected aspect ratio during resizing. What can be the issue?

Viewed 115

I implemented react-image0crop in a project but after testing with different size of images(landscape & portrait)I spotted an issue with cropper frame handler - 3 handlers are working fine marked as green

Problem with red is I am using aspect ratio as aspect : 16/9 so when after I select an image from my computer then cropper frame is appearing with correct aspect ratio but when I drag cropper to bottom and then start resizing cropper frame using top left using crop frame's handler (marked as red in previous screenshot) it is resizing but aspect ration is not maintaining during this resizing process code sand box link is here - https://codesandbox.io/s/72py4jlll6

here is complete code - `

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 pixelRatio = window.devicePixelRatio;
    const scaleX = image.naturalWidth / image.width;
    const scaleY = image.naturalHeight / image.height;
    const ctx = canvas.getContext('2d');
canvas.width = crop.width * pixelRatio * scaleX;
canvas.height = crop.height * pixelRatio * scaleY;

ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
ctx.imageSmoothingQuality = 'high';

ctx.drawImage(
  image,
  crop.x * scaleX,
  crop.y * scaleY,
  crop.width * scaleX,
  crop.height * scaleY,
  0,
  0,
  crop.width * scaleX,
  crop.height * scaleY
);

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',
    1
  );
});

}

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(, document.getElementById('root')); `

0 Answers
Related