Search code examples
javascriptjquerykonvajs

Conver konvajs canvas to image and load these image to another canvas


I tried to build many konvajs canvas and transform them to konva images. And finally load these images to another canvas and show.

function main(){
    var total_konva_stage= createStage();
    var imagesLayer= new Konva.Layer();
    for (var key in  array){
         $(".tmpcontainer").remove();
         containerName = containerNameBase + key;
         $("#hidden_div").append("<div id='"+containerName+"'  class='tmpcontainer'></div>");

         var konva_stage =createcanvas(containerName);  //create a hidden dynamic div and bind this stage to it
         var img  = konva_stage .toDataURL("image/png");
         var imageObj = new Image();
         imageObj.src = img
         imageObj.onload = function() {
             callback_canvastoImg(imagesLayer, imageObj);
         };
     }
     total_konva_stage.add(imagesLayer);
     total_konva_stage.show();
     total_konva_stage.draw();
}
function callback_canvastoImg(imagesLayer, imageObj){
      var konva_image = new Konva.Image({imageObj}); 
      imagesLayer.add(konva_image );
}

What I think my results is that "total_konva_stage" will have every separate img that from konva_stage.

But I found my second img will contain the first img , my third img contain the first, second img

I have no idea now, please help. Thanks


Solution

  • onload function callback is asynchronous. It means it will be executed only after the whole array is processed.

    So in this line: callback_canvastoImg(imagesLayer, imageObj); variable imageObj will refer to the LAST created image.

    To avoid this you can:

    1. Use modern js syntax of declaring variables (in case you should use something like babel)

      const imageObj = new Image();
      
    2. You can define closure function for loop iteration. You just need to use array.forEach instead of for loop:

      array.forEach(function(item, key) {
        $(".tmpcontainer").remove();
        containerName = containerNameBase + key;
        $("#hidden_div").append("<div id='"+containerName+"'  class='tmpcontainer'></div>");
      
        var konva_stage =createcanvas(containerName);  //create a hidden dynamic div and bind this stage to it
        var img  = konva_stage .toDataURL("image/png");
        var imageObj = new Image();
        imageObj.src = img
        imageObj.onload = function() {
           callback_canvastoImg(imagesLayer, imageObj);
        };
      }