Code Monkey home page Code Monkey logo

Comments (15)

lucasprins avatar lucasprins commented on September 26, 2024 9
function onSubmitCrop() {
    if (completedCrop) {
      // create a canvas element to draw the cropped image
      const canvas = document.createElement("canvas");

      // get the image element
      const image = imgRef.current;

      // draw the image on the canvas
      if (image) {
        const crop = completedCrop;
        const scaleX = image.naturalWidth / image.width;
        const scaleY = image.naturalHeight / image.height;
        const ctx = canvas.getContext("2d");
        const pixelRatio = window.devicePixelRatio;
        canvas.width = crop.width * pixelRatio * scaleX;
        canvas.height = crop.height * pixelRatio * scaleY;

        if (ctx) {
          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
          );
        }

        const base64Image = canvas.toDataURL("image/png"); // can be changed to jpeg/jpg etc

        if (base64Image) {
          // @ts-ignore
          const fileType = base64Image.split(";")[0].split(":")[1];

          const buffer = Buffer.from(
            base64Image.replace(/^data:image\/\w+;base64,/, ""),
            "base64"
          );
          const file = new File([buffer], fileName, { type: fileType });
          onSubmit(file); // function passed as a prop
        }
      }
    }
  }

If anyone is still having trouble, this is how I did it.

from react-image-crop.

sekoyo avatar sekoyo commented on September 26, 2024 2

from react-image-crop.

sekoyo avatar sekoyo commented on September 26, 2024 1

from react-image-crop.

Joshuajrodrigues avatar Joshuajrodrigues commented on September 26, 2024

Hey did you figure thus out by any chance ?

from react-image-crop.

Joshuajrodrigues avatar Joshuajrodrigues commented on September 26, 2024

Is there a possibility to do this without canvas ? Like what if the user doesnt want a preview. Just drop, crop and submit ?

from react-image-crop.

andersr avatar andersr commented on September 26, 2024

@dominictobias thanks for this tip. By offscreen, is this simply a css-based off screen, or are you referring to this: https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas

from react-image-crop.

sekoyo avatar sekoyo commented on September 26, 2024

from react-image-crop.

Joshuajrodrigues avatar Joshuajrodrigues commented on September 26, 2024

Hey sorry to disturb here again but how would you handle this for a circular crop ?

from react-image-crop.

sekoyo avatar sekoyo commented on September 26, 2024

Hey sorry to disturb here again but how would you handle this for a circular crop ?

I’ve not personally tried to do a circle crop to canvas. Normally I’d say just do it with CSS for reasons explained here - #409 (comment)

but if you want to create a downloadable version with a circle you’d have to do it on the canvas as a black circular border or something ⚫️ which I haven’t tried to do before but if you can find some code to do it, then you can just paste it after the other canvas code to do it over the top

from react-image-crop.

sekoyo avatar sekoyo commented on September 26, 2024

I was thinking with CSS but this sounds like a better solution 👍

for example:

https://pqina.nl/blog/applying-a-circular-crop-mask-to-an-image/#applying-a-circular-mask-using-canvas

from react-image-crop.

sekoyo avatar sekoyo commented on September 26, 2024

You can create a hidden link:

const hiddenAnchorRef = useRef<HTMLAnchorElement>(null)
const blobUrlRef = useRef('')

<a
  ref={hiddenAnchorRef}
  download
  style={{
    position: 'absolute',
    top: '-200vh',
    visibility: 'hidden',
  }}
>
  Hidden download
</a>

And you can create a blob, create a URL with the blob, assign it to the anchor, trigger a click:

function onDownloadCropClick() {
    if (!previewCanvasRef.current) {
      throw new Error('Crop canvas does not exist')
    }

    previewCanvasRef.current.toBlob((blob) => {
      if (!blob) {
        throw new Error('Failed to create blob')
      }
      if (blobUrlRef.current) {
        URL.revokeObjectURL(blobUrlRef.current)
      }
      blobUrlRef.current = URL.createObjectURL(blob)
      hiddenAnchorRef.current!.href = blobUrlRef.current
      hiddenAnchorRef.current!.click()
    })
  }

Note that if you doubled the size of the canvas on e.g. retina screens to get extra sharpness (I do this in canvasPreview.ts based on window.devicePixelRatio), then you also need to size the canvas down by a factor of window.devicePixelRatio which makes things more complicated. You would have to copy to an offscreen canvas that is a normal size first.

from react-image-crop.

AnnieTaylorCHEN avatar AnnieTaylorCHEN commented on September 26, 2024
function onSubmitCrop() {
    if (completedCrop) {
      // create a canvas element to draw the cropped image
      const canvas = document.createElement("canvas");

      // get the image element
      const image = imgRef.current;

      // draw the image on the canvas
      if (image) {
        const crop = completedCrop;
        const scaleX = image.naturalWidth / image.width;
        const scaleY = image.naturalHeight / image.height;
        const ctx = canvas.getContext("2d");
        const pixelRatio = window.devicePixelRatio;
        canvas.width = crop.width * pixelRatio * scaleX;
        canvas.height = crop.height * pixelRatio * scaleY;

        if (ctx) {
          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
          );
        }

        const base64Image = canvas.toDataURL("image/png"); // can be changed to jpeg/jpg etc

        if (base64Image) {
          // @ts-ignore
          const fileType = base64Image.split(";")[0].split(":")[1];

          const buffer = Buffer.from(
            base64Image.replace(/^data:image\/\w+;base64,/, ""),
            "base64"
          );
          const file = new File([buffer], fileName, { type: fileType });
          onSubmit(file); // function passed as a prop
        }
      }
    }
  }

This works magic! For anyone with buffer error, just npm i buffer and import {Buffer} from 'buffer'; it should solve the issue.

If your backend is using multer package to parce, you can do

const formDataForImage = new FormData();
 formDataForImage.append('file', fileCropped);

then attach that formDataForImage as obj in the body in the post request, it should work.

from react-image-crop.

AnnieTaylorCHEN avatar AnnieTaylorCHEN commented on September 26, 2024

@dominictobias Can you also add the above solution in the documentation as reference? Thanks!

from react-image-crop.

AnnieTaylorCHEN avatar AnnieTaylorCHEN commented on September 26, 2024

Hi, it worked locally in dev but I ran into a lot of issues with the build because of the Buffer. 😅 Currently using Vite/React and I have referred to this solution:
https://stackoverflow.com/questions/72773373/buffer-is-not-exported-by-vite-browser-externalbuffer

I used the OP's inject method:

rollupOptions: {
        plugins: [inject({Buffer: ['Buffer', 'Buffer']})],
        external: ['Buffer'],
      },

but I am getting errors
Uncaught TypeError: Failed to resolve module specifier "Buffer". Relative references must start with either "/", "./", or "../".
in deployment ( it pass the build in pipeline). So I don't think I write it correctly.... I know this is probably a Vite related issue, but in case anyone knows, please give me some tip on how to fix this? Thanks! 🙏

from react-image-crop.

AnnieTaylorCHEN avatar AnnieTaylorCHEN commented on September 26, 2024

Hi, I solved my issues now:

By now I completely ditched the previous solution.

  1. npm i process buffer.
  2. add those to the index.html, just under
<script>
      window.global = window;
    </script>
    <script type="module">
      import {Buffer} from 'buffer/'; // <-- no typo here ("/")
      import process from 'process';
      window.Buffer = Buffer;
      window.process = process;
    </script>
  1. in vite.config.ts
 resolve: {
      alias: {
        process: 'process/browser',
      },
    },
    ```
4. in the component where you need buffer, `import {Buffer} from 'buffer/index.js';`

from react-image-crop.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.