Search code examples
javascripthtmlcanvashtml5-canvasfabricjs

fabric.js - toDataURL shows blank page when there is image on canvas


I'm using fabric.js for my canvas application, toDataURL method works properly except when there is a image on canvas. When i add an image to canvas and call toDataURL it shows me a blank page.

//When i call it from chrome console
canvas.toDataURL();
//It returns a working data url with no problem.
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAAGkCAYAAAAPPajHAAAgAElEQ…fpmwgogX1TrjoqP0FACewngtZh+iYCSmDflKuOyk8Q+H+CKCqUW0spTgAAAABJRU5ErkJggg=="

//When i execute same code in a .js file it returns a data url which shows a blank image.
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAAGkCAYAAAAPPajHAAAKC0lEQ…sBAmEBAw6XJzoBA/YDBMICBhwuT3QCBuwHCIQFDDhcnugEHt/IAaW9dzALAAAAAElFTkSuQmCC"

It's interesting that it's working on chrome dev console but not works in .js file even if it's same code. I noticed that working data url finishes with '==' but other one not. However i don't know what this means.


Solution

  • You didn't give much to analyze but I'll go from there on my gut feeling.

    The image you are using is probably violating Cross-Origin Resource Sharing (CORS) requirements. When this happens the canvas will return a blank image when you try to get the pixel data either by using canvas.toDataURL() or context.getImageData().

    It basically happens when the image is not located on the same domain as the page or is loaded from the file:// protocol.

    You can try to add the following to the image object before setting the source:

    image.crossOrigin = 'anonymous';
    image.src = '...';
    

    From tag:

    <img crossOrigin='anonymous' src='...' alt='' />
    

    This will request permission from the server to use the image cross-origin. If the server allows you should be fine.

    If not you will either have to copy the image to your own server so it loads from the same domain as your page, or create a proxy page that loads the image externally and serves it to your page from the proxy page (it sounds complicated but really isn't).

    If the image does not show up at all on the canvas you are probably not using load callback which you need since image loading is asynchronous. If so just add:

    image.onload = function() {
        /// now you can draw the image to canvas
    }
    image.crossOrigin = 'anonymous';
    image.src = '...';