question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Changing crop to use aspect throws an error

See original GitHub issue

Using the following example code throws a type error:

Failed to execute ‘drawImage’ on ‘CanvasRenderingContext2D’: The provided value is not of type ‘(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)’

import React from "react";
import ReactDOM from "react-dom";
import ReactCrop, { makeAspectCrop } from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";

import "./styles.css";

class App extends React.Component {
  state = {
    src: null,
    crop: {
      x: 10,
      y: 10,
      aspect: 1,
      height: 80
    }
  };

  onSelectFile = e => {
    if (e.target.files && e.target.files.length > 0) {
      const reader = new FileReader();
      reader.addEventListener(
        "load",
        () =>
          this.setState({
            src: reader.result
          }),
        false
      );
      reader.readAsDataURL(e.target.files[0]);
    }
  };

  onImageLoaded = async (image, pixelCrop) => {
    this.setState({ image });
    if (pixelCrop) {
      const finalImage = await this.getCroppedImg(
        image,
        pixelCrop,
        "newFile.jpeg"
      );
      this.setState({ finalImage });
    }
  };

  onCropComplete = async (crop, pixelCrop) => {
    const finalImage = await this.getCroppedImg(
      this.state.image,
      pixelCrop,
      "newFile.jpeg"
    );
    this.setState({ finalImage });
  };

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

  getCroppedImg(image, pixelCrop, fileName) {
    const canvas = document.createElement("canvas");
    canvas.width = pixelCrop.width;
    canvas.height = pixelCrop.height;
    const ctx = canvas.getContext("2d");

    ctx.drawImage(
      image,
      pixelCrop.x,
      pixelCrop.y,
      pixelCrop.width,
      pixelCrop.height,
      0,
      0,
      pixelCrop.width,
      pixelCrop.height
    );

    // As Base64 string
    // const base64Image = canvas.toDataURL('image/jpeg');

    // As a blob
    return new Promise((resolve, reject) => {
      canvas.toBlob(file => {
        file.name = fileName;
        resolve(file);
      }, "image/jpeg");
    });
  }

  render() {
    return (
      <div className="App">
        <div>
          <input type="file" onChange={this.onSelectFile} />
        </div>
        {this.state.src && (
          <ReactCrop
            src={this.state.src}
            crop={this.state.crop}
            onImageLoaded={this.onImageLoaded}
            onComplete={this.onCropComplete}
            onChange={this.onCropChange}
          />
        )}
        <img
          src={
            this.state.finalImage &&
            window.URL.createObjectURL(this.state.finalImage)
          }
        />
      </div>
    );
  }
}

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

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
JavaMajkcommented, Oct 25, 2018

Nevermind I misread your issue, this happens because when using an aspect from it calls onChange and onCropComplete with the filled in crop so it gets set to state. This happens before the onImageLoad event so you can add a safeguard:

onCropComplete = async (crop, pixelCrop) => {
    if (this.state.image) {
      const croppedImageUrl = await this.getCroppedImg(
        this.state.image,
        pixelCrop,
        "newFile.jpeg"
      );
      this.setState({ croppedImageUrl });
    }
  };

Yeah perfect, thats about how I solved it. just got puzzled as it did not happen with just using height & width instead of aspect in the crop object. Thank you for your prompt reply and help @DominicTobias! 💯

0reactions
DominicTobiascommented, Oct 25, 2018

Released in 6.0.2 and updated sandbox demo, see note on setting image ref to state:

Patch release to change order of calls when using aspect crops - onImageLoaded is called before onChange and onComplete so that getting an image reference before making a crop on the client is more convenient in this situation. Note that if you set the image ref to state (which is probably unnecessary), then it won’t exist by the time onChange and onComplete are called so it’s recommended that you don’t. Refer to the sandbox example if you’re confused.

I’m going to make another change soon so that onChange and onComplete are called when you pass an initial crop so you don’t have to set the crop in multiple places.

Read more comments on GitHub >

github_iconTop Results From Across the Web

java - Adding @Aspect throws BeanCreationException
Even the beans which are using XML based configuration for aspects, are not getting created. It is throwing some BeanCreationException .
Read more >
ACF image Crop Migration - WordPress.org
Where I see the error “Failed to crop image” is when I remove the existing image, and select a new image from the...
Read more >
The Many Different Ways to Use the Crop Effect in Premiere Pro
Here are six ways the crop effect in Adobe Premiere Pro will improve your filmmaking workflow — and yield more satisfying results.
Read more >
Change the aspect ratio of an image using CSS - gavsblog
In this post I'll show you how to change the aspect ratio of an image or element using CSS, and explain why this...
Read more >
How To Change the Divi Gallery Image Aspect Ratio
That one actuallyy make the gallery use the original uploaded image aspect ratio instead. How To Stop Image Crop In The Divi Blog...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found