2011-02-07 27 views
21

我加载(大)动态图像绘制成HTML5画布,这样的事情:取消在HTML5的浏览器单一的图像请求

var t = new Image(); 
t.onload = ... 
t.src = 'http://myurl'; 

但每过一段时间想取消图像完全请求

我想出的唯一方法是将src设置为''。即

t.src = '' 

这适用于许多浏览器,但似乎只有Firefox实际上取消了图像的http请求。

我通过禁用高速缓存并启用“模拟调制解调器速度”来测试Fiddler2。然后运行a fiddle to test canceling a image request.(我很想听听关于如何测试的其他想法)

我知道有一些方法可以取消所有请求(as in this question),但我只想取消一个。

有关其他方式(特别是在移动浏览器上)的任何想法?

+4

警惕't.src =''`,该规范模糊了应该发生的事情。见http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/ – 2011-02-07 20:55:39

+1

正确...一些浏览器正在请求网页的网址(或base url)试图用`src =''`加载图像。在Firefox下,设置`t.src = null`也会取消请求,但是对其他人不做任何处理。较新的(当前工作)规范说(在某些情况下)[应该引发错误](http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1 .html#update-the-image-data)... kindof。 – Amir 2011-02-07 23:01:43

+3

在Firefox中将`src`设置为嵌入式图像也会取消以前的请求:`t.src ='data:image/gif; base64,R0lGOD ...`在[this fiddle]中看到它(http:// jsfiddle。 net/amirshim/F4HbT/21 /) – Amir 2011-02-07 23:16:47

回答

13

这是我设法使其在所有现代浏览器(Chrome,Safari,Mobile-Safari,Firefox和IE9)中都能正常工作的唯一方法。

  • 加载一个空和隐藏iframe
  • 追加一个image tagbodyiframe
  • img.onload完成后,您可以使用图像DOM元素绘制为HTML5画布drawImage()
  • 如果要取消加载,请在iframecontentWindow(或IE中的contentDocumentexecCommand("stop", false))上发出stop()
  • 取消图片加载后,您可以重新使用iframe加载更多图片。

我在GitHub上创建了这个类,并把CoffeeScript的代码(和它的编译的JavaScript): Cancelable Html5 Image Loader

如果你想用它玩,我还创建了一个jsfiddle to test it out。记得启动Fiddler2(或类似的东西),看看实际的网络请求是否真的被取消。

4

您可以尝试window.stop()来停止所有请求,但不是单个请求。在IE中,它不是window.stop(),它是document.execCommand(“Stop”,false)。

如果你有其他需求明智的东西,那么这样做会干扰它。 (你会后续重新请求你仍然想要的资源,但这太辛苦了)。


所以,如果你想停下来一个大的图像一个请求,你可以做的是图像加载到文档中隐藏的iframe内。 IFRAME的onload事件可以用来将图像加载到主文档中,到那时它应该被缓存(假设你已经配置了缓存指令)。

如果图片过长,则可以访问IFRAME的contentWindow并发出停止命令。

您需要拥有尽可能多的IFRAME元素,因为可以同时请求图像。

+0

“但不是个人的”......你可以支持这个吗?您提供的其他信息已经在问题中陈述并链接到了。 – Amir 2011-02-08 22:52:57

2

我怀疑有一种跨浏览器的方式可以在没有黑客的情况下做到这一点。一个建议是向服务器端脚本发出AJAX请求,该脚本返回图像的Base64编码版本,然后您可以将其设置为src属性。然后,如果您决定取消加载图像,则可以取消该请求。如果你想逐渐显示图像,这可能很困难。

2

我实际上有同样的问题,并做了一些测试。

我已经做了一些测试iframes并取得了一些成功。经过Firefox 3.6和Chrome测试。对于我使用的9个15Mb的图像。有了img预加载,我多次杀死了我的firefox(是的,在这台计算机上没有太多的记忆),使用img“暂停”动作并不会阻止图像加载,如果请求已经开始,iframes暂停动作真的会停止下载(如我删除iframe)。下一步将用XMLHttpRequests进行测试。由于我的测试代码的这个版本正在使用图片url的braowser缓存行为来防止第二次加载,并且这也适用于ajax请求。但也许与iframe我可以找到一种方法来从iframe中直接加载的图像中检索二进制数据(限制在相同的域名url)。

这是我的测试代码(非常快的浏览器,可太多的非常大的图像杀死你的Firefox):

// jQuery.imageload.shared.list contains an array of oversized images url 
jQuery.each(imglist,function(i,imgsrc) { 

    name = 'imageload-frame'; 
    id = name + "-" + i; 
    // with img it is not possible to suspend, the get is performed even after remove 
    //var loader = jQuery('<img />').attr('name', name).attr('id',id); 
    var loader = jQuery('<iframe />').attr('name', name).attr('id',id); 

    //no cache on GET query taken from jQuery core 
    // as we really want to download each image for these tests 
    var ts = +new Date; 
    // try replacing _= if it is there 
    var ret = imgsrc.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2"); 
    // if nothing was replaced, add timestamp to the end 
    imgsrc = imgsrc + ((ret == imgsrc) ? (imgsrc.match(/\?/) ? "&" : "?") + "_=" + ts : ""); 

    loader.css('display', 'none').appendTo('body'); 
    loader.after(jQuery('<a>') 
      .text(' stop ') 
      .attr('href','#') 
      .click(function(){ 
       loader.remove(); 
       jQuery(this).text(' suspended '); 
      }) 
    ); 

    // start the load - preload 
    loader.attr('src',imgsrc); 

    // when preload is done we provide a way to get img in document 
    loader.load(function() { 
     jQuery(this).next("a:first") 
      .text(" retrieve ").unbind('click') 
      .click(function() { 
       var finalimg = jQuery('<img />'); 
       // browser cache should help us now 
       // but there's maybe a way to get it direclty from the iframe 
       finalimg.attr('src',loader[0].src); 
       finalimg.appendTo('body'); 
      }); 
    }); 
}); 

编辑,这里是fillde来测试它:http://jsfiddle.net/wPr3x/