2017-06-06 1 views
0

Je suis en train de construire une application, dans laquelle un utilisateur peut télécharger plusieurs images et travailler avec elles simultanément. Comme certains processus sont mal exécutés en raison de fichiers d'image volumineux, je veux les redimensionner avant que l'utilisateur ne les obtienne.Comment retourner une fonction avec img.onload?

Dans ma fonction resizer(), j'essaie de redimensionner à l'aide de canvas. Cela fonctionne, mais puisque le 'canvas.toDataURL()' est dans la fonction img.onload, je ne sais pas comment retourner la valeur et l'analyser à la fonction handleFiles().

aussi ... J'ai essayé quelques cas où j'ai obtenu un code de la handleFiles() - comme:

var preview = document.getElementById("img"+count); 
var surface = document.getElementById("cubface"+count); 
var count = counterImg(); 
preview.src = resizer(e.target.result, count); 
surface.src = resizer(e.target.result, count); 

et les mettre à la fin de la fonction img.onload comme

var preview = document.getElementById("img"+number); 
var surface = document.getElementById("cubface"+number); 
preview.src = canvas.toDataURL; 
surface.src = canvas.toDataURL; 

I J'ai le redimensionnement, mais je n'ai que la dernière image de la boucle à traiter.

Ainsi, les questions sont les suivantes:

  1. Dans la fonction resizer(), comment retourner la valeur canvas.toDataURL qui est en img.onload? Pourquoi la boucle ne couvre que la dernière instance et pas toutes les images et comment résoudre ce problème?

code complet:

JavaScript:

function resizer(base64, number){ 

    // Max size for thumbnail 
    if(typeof(maxWidth) === 'undefined') maxWidth = 1200; 
    if(typeof(maxHeight) === 'undefined') maxHeight = 1200; 

    var img = new Image(); 
    img.src = base64; 

    // Create and initialize two canvas 
    var canvas = document.createElement("canvas"); 
    var ctx = canvas.getContext("2d"); 
    var canvasCopy = document.createElement("canvas"); 
    var copyContext = canvasCopy.getContext("2d"); 

    img.onload = function() { 

     // Determine new ratio based on max size 
     var ratio = 1; 
     if (img.width > maxWidth) 
      ratio = maxWidth/img.width; 
     else if (img.height > maxHeight) 
      ratio = maxHeight/img.height; 

     // Draw original image in second canvas 
     canvasCopy.width = img.width; 
     canvasCopy.height = img.height; 
     copyContext.drawImage(img, 0, 0); 

     // Copy and resize second canvas to first canvas 
     canvas.width = img.width * ratio; 
     canvas.height = img.height * ratio; 
     ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height); 

     return canvas.toDataURL(); 

    }; 

    return img.onload; 

} 


function handleFiles(files) { 
    for (var i = 0; i < files.length; i++) { 
     var file = files[i]; 
     var count = counterImg(); 
     var preview = document.getElementById("img"+count); 
     var surface = document.getElementById("cubface"+count); 

     var reader = new FileReader(); 
     reader.onload = (function (preview, surface) { 
      return function (e) { 
       var newimage = resizer(e.target.result, count); 
       preview.src = newimage; 
       surface.src = newimage; 
       $('#image-cropper'+count).cropit('imageSrc', e.target.result); 
      } 
     })(preview, surface); 
     reader.readAsDataURL(file); 
    } 
} 
+0

Êtes-vous sûr que $ ('# image Cropper '+ compte') le nombre de variables est correctement défini?Vous pourriez vouloir l'ajouter à votre fonction (aperçu, surface). – user3220633

+0

c'est juste cette fonction: 'var j = 0; function counterImg() { j ++; return j; } ' – PLAYCUBE

Répondre

1

Le nombre variable n'est pas scope correctement.

Il y a un délai entre le moment où vous déclarez la fonction et le moment où vous l'utilisez, par conséquent, chaque exécution se termine avec la même valeur. Ainsi, le sélecteur jquery retournera toujours le même élément. Ce qui explique pourquoi seule la dernière image est modifiée.

Voici un jsfiddle qui illustre l'exécution.

https://jsfiddle.net/Lc6bngv5/1/

Pour résoudre ce problème, il suffit de passer compter à la fonction qui encapsulent votre aperçu et de la surface:

reader.onload = (function (preview, surface, count) { 
     return function (e) { 
      var newimage = resizer(e.target.result, count); 
      preview.src = newimage; 
      surface.src = newimage; 
      $('#image-cropper'+count).cropit('imageSrc', e.target.result); 
     } 
    })(preview, surface, count); 

Pour la deuxième question:

La fonction Redimensionner retourne une fonction. Il ne retourne pas le résultat de cette fonction. Pour obtenir l'URL correctement, j'utiliser une fonction de rappel:

reader.onload = (function (preview, surface, count) { 
    return function (e) { 
     var newimage = resizer(e.target.result, count, function(url){ 
      preview.src = url; 
      surface.src = url; 
      $('#image-cropper'+count).cropit('imageSrc', e.target.result); 
     }); 
    } 
})(preview, surface, count); 

Et vous devez faire les modifications suivantes Redimensionner:

function resizer(base64, number, cb){ 
    ... 
    img.onload = function() { 
     ... 
     // return canvas.toDataURL(); 
     cb(canvas.toDataURL()); 
    }; 
} 
+0

Wow, merci pour vos conseils! Cela a résolu la deuxième question. Une idée de comment faire le retour dans 'img.onload', donc je peux analyser' canvas.toDataURL(); 'à' handeFiles() '? – PLAYCUBE

+1

J'ai ajouté une modification, vous pourriez utiliser une fonction de rappel, qui vous permettrait d'obtenir le résultat correctement. – user3220633

+0

Merci! C'était génial! – PLAYCUBE