0

I have a desktop application using Electron platform and Javascript where I am converting an HTML5 canvas to JPEG using:

<a id="download" download="Path.jpg">Download JPG</a>

then,

function download(){ 
    dt = 'data:text/plain,foo'; 
    this.href=dt; }

This refreshes my whole application.

Since the user is drawing on the canvas, I do not want to refresh the page, only allowing the image to be downloaded and then the user may continue to draw on the canvas.

Any pointers on what I am doing wrong and how this behavior can be changed?

The image below is a screenshot in which you can see the canvas behind with a blue square drawn. As soon as I click on the save button, the canvas and the whole page will be refreshed.

enter image description here

rrz0
  • 2,182
  • 5
  • 30
  • 65
  • Try opening a new tab/window with your data-url instead of replacing the current url – Mark Dec 15 '17 at 06:10
  • Can u share your canvas code or created your snippet – Muhammet Can TONBUL Dec 15 '17 at 06:12
  • Hi @Kaiido this is a desktop application using the Electron platform – rrz0 Dec 15 '17 at 06:25
  • 1
    hehe silly me I missed that part... Does the same happen when you do `function download(){ dt = 'data:text/plain,foo'; this.href=dt;}`? If so, you can remove all the canvas and three.js parts of your question, as it would be an Electron bug completely unrelated to canvas, jpeg, three.js – Kaiido Dec 15 '17 at 06:28
  • Yes, the same happens on doing so... Will try to edit accordingly. – rrz0 Dec 15 '17 at 06:34
  • 1
    Are you trying to take the snapshot of the current scene in three.js? – HariV Dec 15 '17 at 06:38
  • That could be another option, but I opted to download the canvas image directly. I will look into your suggestion. – rrz0 Dec 15 '17 at 06:40

2 Answers2

0

I guess you are trying to take a snapshot of your three.js scene. You can use FileSaver.js to download the image to your local machine.

here is the link to FileSaver.js https://github.com/eligrey/FileSaver.js/

include the FileSaver.js in your code

All you have to do is,

1) convert the canvas to dataurl(will give you base64 encoded image)

2) convert the base64 data to blob

3) download the blob to local machine

Function to convert the base64 to blob

var base64ToBlob : function( b64Data, contentType, sliceSize ) {
    return new Promise( function( resolve, reject ){
        contentType = contentType || '';
        sliceSize = sliceSize || 512;
        try{
            //converting each byte in the b64Data to a single character using the atob() method.
            var byteCharacters = atob(b64Data);
            var byteArrays = [];
            // a set of 'sliceSize' number of characters are processed at a time. 
            for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
                //slice holds a set of 'sliceSize' number of characters from the byteCharacters array.
                var slice = byteCharacters.slice(offset, offset + sliceSize);   
                //converting each character in 'slice' to the ASCII code.
                var byteNumbers = new Array(slice.length);
                for (var i = 0; i < slice.length; i++) {
                    byteNumbers[i] = slice.charCodeAt(i);
                }
                //creating a typed array structure using the ASCII codes of the characters.
                var byteArray = new Uint8Array(byteNumbers);
                byteArrays.push(byteArray);
            }
            //now byteArrays holds the whole bytes converted to the ASCII character codes
            //convert the typed array to the blob
            var blob = new Blob( byteArrays, { type : contentType } );
            resolve( blob );
        }
        catch( error ){
            reject( error );
        }
    } );
}

change your download function like this,

function download() {
    var dt = canvas.toDataURL('image/jpeg');
    //this.href = dt; //this line is causing the page redirection
    base64ToBlob( dt, 'image/png', 512 ).then( function( file ){ 
        FileSaver.saveAs(file, "image.png");//or use just saveAs( file, "image.png" )
    }, function( error ){
        console.log( error );
    } );
}
HariV
  • 687
  • 1
  • 10
  • 17
  • This still refreshes the page.. As said correctly by @Kaiido, even `function download(){ dt = 'data:text/plain,foo';}` refreshses the page so this may be something related to Electron. – rrz0 Dec 15 '17 at 06:52
  • are you still using this.href = dt ? – HariV Dec 15 '17 at 06:54
  • hmm, then it may be because of another reason. Can you try renderer.domElement.toDataURL() instead of canvas.toDataURL('image/jpeg'). I am not sure it will help you or not – HariV Dec 15 '17 at 06:58
  • Unfortunately not, still with the same behaviour – rrz0 Dec 15 '17 at 07:04
  • 1
    The problem is with Electron's implementation of the `download` attribute... FileSaver uses this attribute when available, and the issue has nothing to do with the canvas. (and while I'm here, note that you are mixing your Blob's mimetype between jpeg and png, and that you actually don't need this base64ToBlob function in newest browsers, there is a canvas.toBlob method – Kaiido Dec 15 '17 at 07:05
  • 1
    @Kaiido , I don't know whether this is correct or not, if the problem is with the download attribute in the 'a' element 'Download JPG' then will it work, if we change it to a button and perform the 'download' function on click (As per the code I suggested) ?. – HariV Dec 15 '17 at 07:09
  • 2
  • I will see if i can replicate this on a new Electron app, for the question to be clearer. – rrz0 Dec 15 '17 at 07:20
-1
var anchorEvent = document.getElementById("download");
anchorEvent.addEventListener("click", function () {
    var dt = canvas.toDataURL('image/jpeg');
    this.href = dt;
    event.preventDefault();
});

event.preventDefault(); is a reason your page will not refresh. it is preventing you to default refresh functionality of a button.

Negi Rox
  • 3,828
  • 1
  • 11
  • 18
  • OP wants the default behavior: starting the download of their file. – Kaiido Dec 15 '17 at 06:29
  • ok I thought page is refreshing, even after downloading a file. This is because whenever we are attaching a eventlistener its default behavior to refresh after exctuing a functionality. – Negi Rox Dec 15 '17 at 06:45