mostrar - JavaScript carga el progreso de una imagen
jquery (8)
Aquí hay una pequeña actualización del código de Julian Jensen para poder dibujar la imagen en un Canvas después de que se cargue:
xmlHTTP.onload = function( e ) {
var h = xmlHTTP.getAllResponseHeaders(),
m = h.match( /^Content-Type/:/s*(.*?)$/mi ),
mimeType = m[ 1 ] || ''image/png'';
// Remove your progress bar or whatever here. Load is done.
var blob = new Blob( [ this.response ], { type: mimeType } );
thisImg.src = window.URL.createObjectURL( blob );
thisImg.onload = function()
{
if ( callback ) callback( this );
};
};
¿Hay alguna manera en JS de obtener el progreso de una imagen de carga mientras se carga la imagen? Quiero utilizar la nueva etiqueta de progreso de HTML5 para mostrar el progreso de la carga de imágenes.
Ojalá hubiera algo así como:
var someImage = new Image()
someImage.onloadprogress = function(e) { progressBar.value = e.loaded / e.total };
someImage.src = "image.jpg";
Con esto, agregas 2 nuevas funciones en el objeto Image ():
Image.prototype.load = function(url){
var thisImg = this;
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.open(''GET'', url,true);
xmlHTTP.responseType = ''arraybuffer'';
xmlHTTP.onload = function(e) {
var blob = new Blob([this.response]);
thisImg.src = window.URL.createObjectURL(blob);
};
xmlHTTP.onprogress = function(e) {
thisImg.completedPercentage = parseInt((e.loaded / e.total) * 100);
};
xmlHTTP.onloadstart = function() {
thisImg.completedPercentage = 0;
};
xmlHTTP.send();
};
Image.prototype.completedPercentage = 0;
Y aquí usa la función de carga y anexa la imagen en un div.
var img = new Image();
img.load("url");
document.getElementById("myDiv").appendChild(img);
Durante el estado de carga, puede verificar el porcentaje de progreso utilizando img.completedPercentage
.
En realidad, en la última versión de Chrome puedes usarlo.
$progress = document.querySelector(''#progress'');
var url = ''https://placekitten.com/g/2000/2000'';
var request = new XMLHttpRequest();
request.onprogress = onProgress;
request.onload = onComplete;
request.onerror = onError;
function onProgress(event) {
if (!event.lengthComputable) {
return;
}
var loaded = event.loaded;
var total = event.total;
var progress = (loaded / total).toFixed(2);
$progress.textContent = ''Loading... '' + parseInt(progress * 100) + '' %'';
console.log(progress);
}
function onComplete(event) {
var $img = document.createElement(''img'');
$img.setAttribute(''src'', url);
$progress.appendChild($img);
console.log(''complete'', url);
}
function onError(event) {
console.log(''error'');
}
$progress.addEventListener(''click'', function() {
request.open(''GET'', url, true);
request.overrideMimeType(''text/plain; charset=x-user-defined'');
request.send(null);
});
<div id="progress">Click me to load</div>
Intente utilizar el enfoque descrito en este blogs.adobe.com/webplatform/2012/01/13/… También hay una muestra en vivo . Como yo entiendo, es lo que estabas buscando.
La respuesta de Sebastian es excelente, la mejor que he visto para esta pregunta. Sin embargo, hay algunas posibles mejoras. Uso su código modificado así:
Image.prototype.load = function( url, callback ) {
var thisImg = this,
xmlHTTP = new XMLHttpRequest();
thisImg.completedPercentage = 0;
xmlHTTP.open( ''GET'', url , true );
xmlHTTP.responseType = ''arraybuffer'';
xmlHTTP.onload = function( e ) {
var h = xmlHTTP.getAllResponseHeaders(),
m = h.match( /^Content-Type/:/s*(.*?)$/mi ),
mimeType = m[ 1 ] || ''image/png'';
// Remove your progress bar or whatever here. Load is done.
var blob = new Blob( [ this.response ], { type: mimeType } );
thisImg.src = window.URL.createObjectURL( blob );
if ( callback ) callback( this );
};
xmlHTTP.onprogress = function( e ) {
if ( e.lengthComputable )
thisImg.completedPercentage = parseInt( ( e.loaded / e.total ) * 100 );
// Update your progress bar here. Make sure to check if the progress value
// has changed to avoid spamming the DOM.
// Something like:
// if ( prevValue != thisImage completedPercentage ) display_progress();
};
xmlHTTP.onloadstart = function() {
// Display your progress bar here, starting at 0
thisImg.completedPercentage = 0;
};
xmlHTTP.onloadend = function() {
// You can also remove your progress bar here, if you like.
thisImg.completedPercentage = 100;
}
xmlHTTP.send();
};
Principalmente agregué un tipo de mimo y algunos detalles menores. Usar como Sebastian describe. Funciona bien.
Si quieres procesar tu imagen cargada, entonces debes agregar una función más, porque
thisImg.src = window.URL.createObjectURL(blob)
solo comienza a procesar la imagen como un hilo.
Tienes que agregar una nueva función al cuerpo del prototipo de carga, como
this.onload = function(e)
{
var canvas = document.createElement(''canvas'')
canvas.width = this.width
canvas.height = this.height
canvas.getContext(''2d'').drawImage(this, 0, 0)
}
Esto me da dolor de cabeza para darse cuenta :)
Solo para agregar a las mejoras, modifiqué la respuesta de Julian (que a su vez modificó la de Sebastian). He movido la lógica a una función en lugar de modificar el objeto Image
. Esta función devuelve una Promise
que se resuelve con el objeto URL, que solo debe insertarse como el atributo src
de una etiqueta de image
.
/**
* Loads an image with progress callback.
*
* The `onprogress` callback will be called by XMLHttpRequest''s onprogress
* event, and will receive the loading progress ratio as an whole number.
* However, if it''s not possible to compute the progress ratio, `onprogress`
* will be called only once passing -1 as progress value. This is useful to,
* for example, change the progress animation to an undefined animation.
*
* @param {string} imageUrl The image to load
* @param {Function} onprogress
* @return {Promise}
*/
function loadImage(imageUrl, onprogress) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
var notifiedNotComputable = false;
xhr.open(''GET'', imageUrl, true);
xhr.responseType = ''arraybuffer'';
xhr.onprogress = function(ev) {
if (ev.lengthComputable) {
onprogress(parseInt((ev.loaded / ev.total) * 100));
} else {
if (!notifiedNotComputable) {
notifiedNotComputable = true;
onprogress(-1);
}
}
}
xhr.onloadend = function() {
if (!xhr.status.toString().match(/^2/)) {
reject(xhr);
} else {
if (!notifiedNotComputable) {
onprogress(100);
}
var options = {}
var headers = xhr.getAllResponseHeaders();
var m = headers.match(/^Content-Type/:/s*(.*?)$/mi);
if (m && m[1]) {
options.type = m[1];
}
var blob = new Blob([this.response], options);
resolve(window.URL.createObjectURL(blob));
}
}
xhr.send();
});
}
/*****************
* Example usage
*/
var imgContainer = document.getElementById("imgcont");
var progressBar = document.getElementById("progress");
var imageUrl = "https://placekitten.com/g/2000/2000";
loadImage(imageUrl, (ratio) => {
if (ratio == -1) {
// Ratio not computable. Let''s make this bar an undefined one.
// Remember that since ratio isn''t computable, calling this function
// makes no further sense, so it won''t be called again.
progressBar.removeAttribute("value");
} else {
// We have progress ratio; update the bar.
progressBar.value = ratio;
}
})
.then(imgSrc => {
// Loading successfuly complete; set the image and probably do other stuff.
imgContainer.src = imgSrc;
}, xhr => {
// An error occured. We have the XHR object to see what happened.
});
<progress id="progress" value="0" max="100" style="width: 100%;"></progress>
<img id="imgcont" />
para comprobar xmlhttpreq v2, use:
var xmlHTTP = new XMLHttpRequest();
if (''onprogress'' in xmlHTTP) {
// supported
} else {
// isn''t supported
}