在加载图像时,JS是否有办法获取加载图像的进度? 我想使用HTML5的新Progress标签来显示加载图像的进度。
我希望有类似的东西:
var someImage = new Image()
someImage.onloadprogress = function(e) { progressBar.value = e.loaded / e.total };
someImage.src = "image.jpg";
答案 0 :(得分:47)
使用此功能,您可以在Image()对象上添加2个新函数:
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;
在这里你使用加载函数并将图像附加到div上。
var img = new Image();
img.load("url");
document.getElementById("myDiv").appendChild(img);
在加载状态期间,您可以使用img.completedPercentage
检查进度百分比。
答案 1 :(得分:16)
塞巴斯蒂安的回答非常好,这是我见过的最好的问题。但是,有一些可能的改进。我使用他的代码修改如下:
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();
};
主要是我添加了一个mime类型和一些小细节。用塞巴斯蒂安描述。效果很好。
答案 2 :(得分:11)
为了补充改进,我修改了Julian的答案(后者又修改了Sebastian的答案)。我已将逻辑移动到函数而不是修改Image
对象。此函数返回使用URL对象解析的Promise
,只需将其插入src
标记的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" />
答案 3 :(得分:3)
实际上,在最新的Chrome中你可以使用它。
$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);
});
&#13;
<div id="progress">Click me to load</div>
&#13;
答案 4 :(得分:1)
对于xmlhttpreq v2检查,请使用:
var xmlHTTP = new XMLHttpRequest();
if ('onprogress' in xmlHTTP) {
// supported
} else {
// isn't supported
}
答案 5 :(得分:1)
以下是Julian Jensen代码的一个小更新,以便能够在加载后在Canvas中绘制图像:
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 );
};
};
答案 6 :(得分:0)
如果要处理加载的图像,则需要再添加一个函数,因为
thisImg.src = window.URL.createObjectURL(blob)
刚开始将图像作为线程处理。
你必须在load原型体中添加一个新函数,比如
this.onload = function(e)
{
var canvas = document.createElement('canvas')
canvas.width = this.width
canvas.height = this.height
canvas.getContext('2d').drawImage(this, 0, 0)
}
这让我很难实现:)
答案 7 :(得分:-3)
尝试使用此article中描述的方法 还有一个live sample。据我所知,你正在寻找。