0
votes

I have created a webpage that basically displays 2 images side by side.

It has a "download" button, which triggers a vanilla Javascript function, which creates a <canvas> HTML element and concatenates the two images inside of it. It then creates a link with the base64-encoded result image as href and clicks on it:

<a download="image.png" id="dllink" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAAAMnCAYAAABhnf9DAAAgAElEQVR4nOzdR48kD3rn96j03pfv6qo21dVd3qT3JryP9Jll281..."></a>

Here is what the function I'm using looks like:

/** 
 * Create canvas, draw both images in it, create a link with the result
 * image in base64 in the "href" field, append the link to the document,
 * and click on it
 */
function saveImage() {

    // Get left image
    var imgLeft = new Image();
    imgLeft.setAttribute('crossOrigin', 'anonymous');
    imgLeft.src = "imgleft/" + idxImageShownLeft + ".jpg";
    imgLeft.onload = function() {

        // Once the left image is ready, get right image
        var imgRight = new Image()
        imgRight.setAttribute('crossOrigin', 'anonymous');
        imgRight.src = "imgright/" + idxImageShownRight + ".jpg";
        imgRight.onload = function() {

            // Once the right image is ready, create the canvas
            var canv = document.createElement("canvas");
            var widthLeft = parseInt(imgLeft.width);
            var widthRight = parseInt(imgRight.width);
            var width = widthLeft + widthRight;
            var height = imgLeft.height;

            canv.setAttribute("width", width);
            canv.setAttribute("height", height);
            canv.setAttribute("id", "myCanvas");
            canv.setAttribute('crossOrigin', 'anonymous');
            var ctx = canv.getContext("2d");

            // Draw both images in canvas
            ctx.drawImage(imgLeft, 0, 0);
            ctx.drawImage(imgRight, widthLeft, 0);

            // Create PNG image out of the canvas
            var img = canv.toDataURL("image/png");

            // Create link element
            var aHref = document.createElement('a');
            aHref.href = img;
            aHref.setAttribute("id", "dllink");
            aHref.download = "image.png";

            // Append link to document
            var renderDiv = document.getElementById("render");
            renderDiv.replaceChild(aHref, document.getElementById("dllink"));

            // Click on link
            aHref.click();
        }
    }
}

My problem is that this works fine on Firefox, but not on Chrome.

After a bit of investigating, I realized that by setting a breakpoint before the aHref.click(); line in Chrome, it worked fine. I think that it means that the aHref.click(); is called before the <a href="data:image/png;base64,...></a> is ready to be clicked, but I don't know for sure.

  • I couldn't find a duplicate of this topic. What keywords should I use just to be 100% sure?
  • Am I investigating in the right direction?
  • Is there an event I could rely on in order to call aHref.click(); only when it is ready?
2
It works for me, I'm using chrome 46.0.2490.86 (64-bit) on ubuntu. what is the problem ??Alessandro.Vegna
What is the purpose of renderDiv.replaceChild(aHref, document.getElementById("dllink")); ? Is aHref , #dlink same element ?guest271314
@Alessandro.Vegna: The problem is that when I click the "download" button, sometimes, the result image is opened in my image editor, and sometimes nothing happens.Alfred Dupont
@guest271314: What I'm doing is replacing the previous #dllink element with the new one (aHref).Alfred Dupont
Not related to your issue, but canvas doesn't have a crossorigin attribute. For your issue, are you sure the images onload events are triggered? I personally always prefer setting the src after I declared the onload handlers. Also, I think that on some UAs, the link has to be visible so the click() can work.Kaiido

2 Answers

0
votes

You could wrap it in an init function that gets called when the window completes loading.

function init() {
  aHref.click();
}
window.onload = init; 

Its similar to the vanilla equivalent of jQuery's .ready() method.

0
votes

aHref , document.getElementById("dllink") appear to be same element ? Though "dllink" has not yet been appended to document when .replaceChild called ?

Try substituting

renderDiv.appendChild(aHref);

for

renderDiv.replaceChild(aHref, document.getElementById("dllink"));