IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

<A download> Gestion évènement de fin de téléchargement onload, onprogress ...


Sujet :

JavaScript

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2022
    Messages : 4
    Par défaut <A download> Gestion évènement de fin de téléchargement onload, onprogress ...
    Bonjour,
    J’utilise un canvas WebGL pour générer les images d’une animation.
    La solution pour générer une vidéo avec le MediaRecorder ne donne que de mauvais résultats au niveau de la qualité de l’image.
    Je génère donc chaque image de l’animation en png ou en jpeg et crée l’image a partir d’un blob avec la fonction toBlob du canevas, j’utilise ensuite une application externe comme DaVinci Resolve ou OpenShot video editor pour constituer la vidéo haute résolution à partir des images.

    À chaque frame dessinée, j’appelle la routine suivante*:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    canevas.toBlob(function (blob) {
    	let urlPhoto = URL.createObjectURL(blob);
    	let link = document.createElement("a");
    	link.setAttribute("href", urlPhoto);
    	link.setAttribute("download", "Image_" + numéroImage + ".jpg");
     
    	const event = new MouseEvent('click', {
    		view: window,
    		bubbles: true,
    		cancelable: true
    		});
    	link.dispatchEvent(event);
     
    	numéroImage++;
     
    }, "image/jpeg", 1.0);
    Le callback crée un lien vers l’image et simule un clic pour télécharger l’image.
    Cela fonctionne à la cadence d’environ 500 ms pour une frame de 2048x1024 pixels.
    Mais si je descends, par exemple à 25 ms entre chaque frame, les images se retrouvent mélangées*: les téléchargements et l’attribution des numéros d’image ne sont plus dans le bon ordre.

    Ma question est la suivante*:
    Existe-t-il un moyen de savoir quand le téléchargement déclenché par le clic sur un lien <a> avec l’attribut «*download*» a terminé, pour lancer le calcul de l’image suivante.

    Merci de vos réponses

  2. #2
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 099
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 099
    Par défaut
    Bonjour,
    il me semble que ton problème peut se séparer en deux parties : l’ordre des téléchargements, et la numérotation des fichiers.

    Pour l’ordre des téléchargements, je pense que ce n’est pas un problème si les fichiers sont numérotés correctement. Il suffit donc de s’assurer que les utilisations de la variable numéroImage soient faites dans l’ordre.

    La vraie source du problème c’est que la méthode toBlob est asynchrone, elle ne donne pas de garantie sur le moment où ta fonction de rappel est appelée. Il faudrait que tu gères la variable numéroImage dans ta routine mais à l’extérieur de la fonction de rappel.

    Si tu as besoin d’une aide plus précise, montre-nous de quelle manière tu appelles ta routine
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2022
    Messages : 4
    Par défaut
    Merci Watilin pour ta remarque avisée.

    Effectivement toBlob est asynchrone et ma façon d’incrémenter le numéro d’image, global, n’était pas bonne.
    J’ai donc testé en clôturant le nom de l’image dans une fonction de callback pour toBlob construite à chaque itération, dans une boucle créée à partir de setTimeout pour les rappels, et incrémenté en dehors du callback. Résultat : les images étaient bien numérotés dans l’ordre de l’animation, mais il y avait des manques : certains numéros étaient omis. Donc des trous dans l’animation, et impossibilité de détecter quand l'image n'était pas sauvée.

    Seconde solution, qui à l’air de fonctionner, former la boucle de rappel dans le callback de toBlob. En fait, il semble que dispatchEvent soit synchrone dans le cas d’un évènement que l’on a fabriqué. Voici le code, avec les fonctions pour la boucle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    /// Globales
    let AnimationStarted = false;
    let AnimationNuméroDImage = 0;
    let AnimationTime = 25; // ms
    /// Lancer l'enregistrement de l'animation
    function AnimationStart() {
    	if (!AnimationStarted) {
    		AnimationStarted = true;
    		window.setTimeout(AnimationUneImage, AnimationTime);
    	}
    }
    // arrêter l'enregistrement
    function AnimationStop() {
    	AnimationStarted = false;
    }
    // Générer une image, la télécharger et recommencer
    function AnimationUneImage() {
     
    	// [...] CODE WEBGL AFFICHANT L’IMAGE DANS LE CANVAS
     
    	AnimationDownloadFrame();
    }
    // Clôturer le nom de l'image à générer (avec son numéro) et ramener la fonction de callback
    function AnimationBlobCallback(nomImage) {
    	return function (blob) {
    		let urlPhoto = URL.createObjectURL(blob);
    		let link = document.createElement("a");
    		link.setAttribute("href", urlPhoto);
    		link.setAttribute("download", nomImage + ".png");
     
    		const event = new MouseEvent('click', {
    			view: window,
    			bubbles: true,
    			cancelable: true
    		});
     
    		link.dispatchEvent(event);
    		if (AnimationStarted === true) {
    			window.setTimeout(AnimationUneImage, AnimationTime);
    		}
    	}
    }
    // Incémenter le numéro, lancer le téléchargement
    function AnimationDownloadFrame() {
    	let canevas = effecteur.canevas;
    	AnimationNuméroDImage++;
    	canevas.toBlob(AnimationBlobCallback("Img" + AnimationNuméroDImage), "image/png", 1.0);
    }
    Le navigateur se stabilise de lui même, entre le temps de production et le temps de téléchargement.

    Cependant, je n'ai toujours pas trouvé de réponse à ma question initiale, existe-t-il un moyen de savoir si un téléchargement provoqué par le click sur un tag <A download> est terminé.

    PS : cela active le ventilateur.

  4. #4
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 209
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 209
    Par défaut
    Bonjour,
    pas tout regardé mais ... pourquoi passer par un dispatchEvent un link.click() devrait suffire.

    Autre remarque, il serait peut-être intéressant de ne pas recréer ton lien à chaque fois mais juste lui réattribuer les attributs modifiés.

  5. #5
    Expert confirmé
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 099
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 099
    Par défaut
    Citation Envoyé par Charpen Voir le message
    Cependant, je n'ai toujours pas trouvé de réponse à ma question initiale, existe-t-il un moyen de savoir si un téléchargement provoqué par le click sur un tag <A download> est terminé.
    Pas à ma connaissance. Cette partie est gérée par le gestionnaire de téléchargements du navigateur, qui n’a a priori pas de lien avec le JavaScript des pages web.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2022
    Messages : 4
    Par défaut
    Citation Envoyé par NoSmoking Voir le message
    Bonjour,
    pas tout regardé mais ... pourquoi passer par un dispatchEvent un link.click() devrait suffire.

    Autre remarque, il serait peut-être intéressant de ne pas recréer ton lien à chaque fois mais juste lui réattribuer les attributs modifiés.
    Cher NoSmoking,
    Merci, je ne connaissais pas la méthode click() ! C'est plus simple.
    Pour le second point, j'ai testé avec un lien global et la modifications des attributs, cela fonctionne effectivement, en créant moins d'objets.

    Les déclarations de globales deviennent donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    /// Globales
    let AnimationStarted = false;
    let AnimationNuméroDImage = 0;
    let AnimationTime = 25; // ms
    let AnimationLink = document.createElement("a");
    et l'ancien code dans le callback
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    	//let link = document.createElement("a");
    	//link.setAttribute("href", urlPhoto);
    	//link.setAttribute("download", nomImage + ".png");
    	//const event = new MouseEvent('click', {
    	//	view: window,
    	//	bubbles: true,
    	//	cancelable: true
    	//});
    	//link.dispatchEvent(event);
    devient simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	AnimationLink.setAttribute("href", urlPhoto);
    	AnimationLink.setAttribute("download", nomImage + ".png");
    	AnimationLink.click();

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2022
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2022
    Messages : 4
    Par défaut
    Citation Envoyé par Watilin Voir le message
    Pas à ma connaissance. Cette partie est gérée par le gestionnaire de téléchargements du navigateur, qui n’a a priori pas de lien avec le JavaScript des pages web.
    Je vais donc réexplorer la solution d'enregistrement à partir de canvas.captureStream et MediaRecorder.


    Merci pour vos réponses.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 26/06/2012, 18h05
  2. tag c:foreach ne marche pas
    Par daydream123 dans le forum Taglibs
    Réponses: 1
    Dernier message: 22/03/2012, 16h10
  3. Mes tags EL ${myValue} ne fonctionnent pas
    Par muad'dib dans le forum Struts 1
    Réponses: 1
    Dernier message: 18/07/2008, 12h58
  4. [RegEx] URL et tags qui ne s'affichent pas comme il le faut
    Par Bruno.C dans le forum Langage
    Réponses: 2
    Dernier message: 26/01/2008, 13h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo