2013-01-08 25 views
39

在加载图像时,有没有一种方法可以让JS获得加载图像的进度? 我想使用HTML5的新Progress标签来显示加载图像的进度。JavaScript加载图像的进度

我希望能有这样的:

var someImage = new Image() 
someImage.onloadprogress = function(e) { progressBar.value = e.loaded/e.total }; 
someImage.src = "image.jpg"; 
+7

已经看了吗? http://blogs.adobe.com/webplatform/2012/01/13/html5-image-progress-events/ – P1nGu1n

+0

Possibile重复的http://stackoverflow.com/questions/2515142/is-it-possible-to- get-download-progress-of-video-image-in-html5 – freedev

+0

可能的解决方法:使用通用的'... loading'指示器,直到'img.complete && img.naturalWidth> 0' –

回答

-1

尝试使用这个article 所描述的方法也有一个live sample。据我了解,你是在寻找。

+5

这不是完全相同方法作为上面评论中发布的链接? – freedev

+2

我不明白。这似乎是在规范中,但我运行的Chrome 30,我没有看到该事件,发布的示例不起作用。我错过了什么吗? –

+2

@RyanBadour似乎这还没有完成 - https://bugs.webkit.org/show_bug.cgi?id=76102 – emaillenin

35

有了这个,你的图像()对象上添加两个新的功能:

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进度百分比。

+0

你可以使用img object is as a src of img tag。 –

+0

这行是做什么的? parseInt(thisImg.completedPercentage =(e.loaded/e.total)* 100); 它写错了吗? –

+0

哦,它应该工作但是它错了,让我e dit this –

14

塞巴斯蒂安的答案非常好,这是我见过的最好的问题。然而,有一些可能的改进。我用他的代码修改如下:

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类型和一些小的细节。用Sebastian描述。效果很好。

+2

你知道哪些浏览器会支持这个吗?而且是否移动?下面的答案表明XHR解决方案不被所有浏览器支持... –

+0

同意@manakor将很高兴看到在这个答案中提到的浏览器支持 – Bill

+0

@manakor:我发现http://caniuse.com对于像你这样的问题是非常宝贵的。 –

1

为xmlhttpreq v2的检查,可使用:

var xmlHTTP = new XMLHttpRequest(); 
if ('onprogress' in xmlHTTP) { 
// supported 
} else { 
// isn't supported 
} 
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); 
 
});
<div id="progress">Click me to load</div>

+1

Христо:I建议你定义'最新'和'它'是什么。您也可以通过这种方式获得更多赞扬。 –

+0

这是兼容所有的浏览器? – ideeps

0

这是朱利安·詹森,以便能够绘制图像在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); 
      }; 
    }; 
0

如果您想要处理已加载的图像,则必须添加一个以上的功能,因为

thisImg.src = window.URL.createObjectURL(blob) 

只是开始将图像作为一个线程处理。

您必须添加一个新的负载原型的身体功能,如

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

只需添加到改善,我已经修改朱利安的回答(反过来修改了塞巴斯蒂安的回答)。我已将逻辑移至一个函数,而不是修改Image对象。该函数返回一个Promise,解析URL对象,只需将其作为image标记的src属性插入。

/** 
 
* 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" />

+0

这可以转化为一个片段吗? – Zze

+0

@Zze Yea,好主意。 – Parziphal

+0

(说实话,我不知道你是否可以在XML中使用XMLHttpRequest - 但是这会使得这个问题成为一个很好的答案) – Zze