crop image with react - customize react-easy-crop styling

Viewed 1899

I'm trying to make a very simple react component that would crop images with react-easy-crop. Apparently it is possible to customize the style of react-easy-crop module with style prop that takes 3 objects: containerStyle, mediaStyle and cropAreaStyle.

This is the default layout:

enter image description here

I want to expand cropArea to full width of its container and to fit media in it by height (so that we don't see the part of the original image outside of cropArea) but can't figure out how to do it. The cropAreaStyle object doesn't seem to affect width or height since it is calculated and injected in the module file (even after setting disableAutomaticStylesInjection to true).

import React from 'react'
import ReactDOM from 'react-dom'
import Cropper from 'react-easy-crop'
import './styles.css'

class App extends React.Component {
  state = {
    imageSrc:
      'https://img.huffingtonpost.com/asset/5ab4d4ac2000007d06eb2c56.jpeg?cache=sih0jwle4e&ops=1910_1000',
    crop: { x: 0, y: 0 },
    zoom: 1,
    aspect: 1 / 1,
    style: {  containerStyle: { position: "absolute", top: "0", width: "calc(100% - 2px)", height: window.innerWidth, overflow: "hidden", border: "1px solid black" }, 
              mediaStyle: { height: "100%", display: "block" }, 
              cropAreaStyle: {position: "absolute", top: "0", border: "1px solid black", width: "100%", height: "100%" }}
  }

  onCropChange = (crop) => {
    this.setState({ crop })
  }

  onCropComplete = (croppedArea, croppedAreaPixels) => {
    console.log(croppedArea, croppedAreaPixels)
  }

  onZoomChange = (zoom) => {
    this.setState({ zoom })
  }

  render() {
    return (
      <div className="App">
        <div className="crop-container">
          <Cropper
            image={this.state.imageSrc}
            crop={this.state.crop}
            zoom={this.state.zoom}
            aspect={this.state.aspect}
            onCropChange={this.onCropChange}
            onCropComplete={this.onCropComplete}
            onZoomChange={this.onZoomChange}
            style={this.state.style}
            disableAutomaticStylesInjection={true}
          />
        </div>
      </div>
    )
  }
}

const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

This is what I'm trying to achieve:

enter image description here

The black square is cropArea that I can't resize...

I want cropArea to remain square.

Is there an easy way to do this, without changing the module file?

The solution with another module is acceptable also

Thanks in advance

2 Answers

I tried to use the object cropAreaStyle but it's not working, instead use the prop cropSize and don't pass the prop aspect.

In order to get the height of the media pass the prop onMediaLoaded:

onMediaLoad = (mediaSize) => {
    this.setState({
      cropHeight: mediaSize.height,
    });
  };

App.js

import React from 'react';
import ReactDOM from 'react-dom';
import Cropper from 'react-easy-crop';
import './style.css';

class App extends React.Component {
  state = {
    imageSrc:
      'https://img.huffingtonpost.com/asset/5ab4d4ac2000007d06eb2c56.jpeg?cache=sih0jwle4e&ops=1910_1000',
    crop: { x: 0, y: 0 },
    zoom: 1,
    cropHeight: 0,
  };

  onCropChange = (crop) => {
    this.setState({ crop });
  };

  onCropComplete = (croppedArea, croppedAreaPixels) => {
    console.log(croppedArea, croppedAreaPixels);
  };

  onZoomChange = (zoom) => {
    this.setState({ zoom });
  };

  onMediaLoad = (mediaSize) => {
    this.setState({
      cropHeight: mediaSize.height,
    });
  };

  render() {
    const cropSize = {
      height: `${this.state.cropHeight}px`,
      width: '100%',
    };

    return (
      <div className="App">
        <div className="crop-container">
          <Cropper
            image={this.state.imageSrc}
            crop={this.state.crop}
            zoom={this.state.zoom}
            onCropChange={this.onCropChange}
            onCropComplete={this.onCropComplete}
            onZoomChange={this.onZoomChange}
            onMediaLoaded={this.onMediaLoad}
            cropSize={cropSize}
          />
        </div>
      </div>
    );
  }
}

export default App;

Demo: https://stackblitz.com/edit/react-4zmgud

Related