Search code examples
javascriptgoogle-chromecanvaswebtodataurl

Are there any alternatives for using toDataURL in Chrome?


The main problem is that I have to work with many images. And I can't use crossOrigin Attribute for all of them.

My code looks like this:
<script>
var c=document.getElementById('example');
var ctx=c.getContext('2d');
var LeftHand = new Image();
LeftHand.id="imq1";
var RightHand = new Image();
RightHand.id="imq2";
var Body = new Image();
Body.id="imq6";

boyBody.src = "https://getout-s3.s3.amazonaws.com/baseBody/boy-02.png";
LeftHand.src = "https://getout-s3.s3.amazonaws.com/NK4XtQvkZ4MGctZf_.hand(unisex)_13.png ";
RightHand.src = "https://getout-s3.s3.amazonaws.com/OPdFPcU2sORgNmTy_.hand(unisex)_9.png ";
Body.src = "https://getout-s3.s3.amazonaws.com/HRZqrTYSdJXGedgX_.Body_(m)7.png ";

boyBody.onload = function() {
ctx.drawImage(boyBody, 0, 0, boyBody.width/2, boyBody.height/2);
ctx.drawImage(LeftHand, (899 - LeftHand.width/2)/2, (867 - LeftHand.height/2)/2, LeftHand.width/2, LeftHand.height/2);
ctx.drawImage(Underwear, (599 - Underwear.width/2)/2, (845 - Underwear.height/2)/2, Underwear.width/2, Underwear.height/2);
ctx.drawImage(Body, (599 - Body.width/2)/2, (557 - Body.height/2)/2, Body.width/2, Body.height/2);
var img = c.toDataURL("image/png");
document.write('<img src="' + img + '" />');
};
</script>

Solution

  • Browsers don't let programmers export cross-domain content for very good security reasons. Your private banking info is cross-domain content that you don't want give to thieves using the canvas as an export device.

    Therefore, context.toDataURL is disabled immediately after you drawImage a cross-domain image onto canvas. The same disabling is true for context.getImageData. (context.getImageData is another way to export canvas content).

    To allow exporting the canvas content to your users, you will have to host all the images on the same domain as your webpage.

    BTW, you must give all your elements time to load before drawing them. Here's an image loader that loads all your images in advance and then calls start() when all the images are fully loaded. Put your ctx.drawImage's in start().

    // put the paths to your images in imageURLs[]
    var imageURLs=[];  
    imageURLs.push("https://getout-s3.s3.amazonaws.com/baseBody/boy-02.png");
    imageURLs.push("https://getout-s3.s3.amazonaws.com/NK4XtQvkZ4MGctZf_.hand(unisex)_13.png");
    // ...etc, for all images
    
    // the loaded images will be placed in imgs[]
    var imgs=[];
    
    var imagesOK=0;
    loadAllImages(start);
    
    function loadAllImages(callback){
        for (var i=0; i<imageURLs.length; i++) {
            var img = new Image();
            imgs.push(img);
            img.onload = function(){ 
                imagesOK++; 
                if (imagesOK>=imageURLs.length ) {
                    callback();
                }
            };
            img.onerror=function(){alert("image load failed");} 
            img.crossOrigin="anonymous";
            img.src = imageURLs[i];
        }      
    }
    
    function start(){
    
        // the imgs[] array now holds fully loaded images
        // the imgs[] are in the same order as imageURLs[]
    
    }