2011-02-07 3 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/ –

+1

Правильно ... некоторые из браузеров делают запросы на URL страницы (или base url), чтобы попытаться загрузить изображение с помощью 'src = '''. В Firefox установка 't.src = null' также отменяет запрос, но ничего не делает на других. Более новая (текущая работа) спецификация, говорит (в некоторых ситуациях), что [она должна запускать onerror] (http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1 .html # update-the-image-data) ... kindof. – Amir

+3

Установка 'src' встроенного изображения в Firefox также отменяет предыдущий запрос:' t.src = 'data: image/gif; base64, R0lGOD ... 'видеть его в [этой скрипке] (http: // jsfiddle. net/amirshim/F4HbT/21 /) – Amir

ответ

13

Это единственный способ, которым мне удалось заставить его работать во всех современных браузерах (Chrome, Safari, Mobile-Safari, Firefox и IE9).

  • нагрузки пустой и скрытые iframe
  • добавить в image tag к body в iframe
  • когда img.onload завершается, вы можете использовать этот образ DOM элемент рисовать на html5 холст с drawImage()
  • если вы хотите отменить загрузку, введите stop() на iframecontentWindow (или execCommand("stop", false) на contentDocument в IE).
  • после отмены загрузки изображения вы можете повторно использовать iframe для загрузки большего количества изображений.

Я создал класс для этого, и поместить код CoffeeScript (и это скомпилированный JavaScript) на GitHub: Cancelable Html5 Image Loader

Если вы хотите, чтобы играть с ним, я также создал jsfiddle to test it out. Не забудьте запустить Fiddler2 (или что-то в этом роде), чтобы увидеть, что фактический сетевой запрос действительно отменяется.

+0

+1 спасибо за этот взлом. Было бы неплохо найти способ предоставить somthing для более старой версии IE без canvas, возможно, с libs, которые добавляют поддержку canvas в IE. – regilero

+0

@ Амир, как мы можем реализовать это в запросах плитки openlayers? – Myra

+0

@Amir У меня такая же проблема, и я попытался воспроизвести ваш скрипт, но я не могу заставить метод iframe.contentWindow.stop() работать. Есть ли способ взглянуть на него? – Ming

4

Вы можете попробовать window.stop(), чтобы остановить все запросы, но не отдельные. В IE это не window.stop(), это document.execCommand («Стоп», ложь).

Если у вас есть другие вещи, идущие по запросу, то это будет мешать ему. (Вы будете следить за повторным запросом ресурсов, которые вы все еще хотите, но это слишком похоже на тяжелую работу).


Так что если вы хотите, чтобы остановить один запрос на большое изображение, что вы могли бы сделать, это загрузить изображение в документ в скрытом IFRAME. Событие onload IFRAME можно использовать для загрузки изображения в основной документ, и к этому времени он должен быть кэширован (предположим, что у вас есть директивы кэширования, настроенные для этого).

Если изображение занимает слишком много времени, вы можете получить доступ к контенту содержимого IFRAME и выдать команду stop.

Необходимо иметь столько элементов IFRAME, сколько есть изображений, которые могут запрашиваться одновременно.

+0

«но не отдельные» ... можете ли вы поддержать это? Остальная информация, которую вы предоставили, уже была сформулирована и связана с вопросом. – Amir

+0

Вы можете остановить только все выполняемые запросы для окна. Что дает мне представление, см. Дополнительную информацию, добавленную в мой ответ! –

2

Я сомневаюсь, что есть кросс-браузерный способ сделать это без хаков. Одно из предложений заключается в том, чтобы сделать запрос AJAX на серверный скрипт, который возвращает кодированную версию Base64 изображения, которую затем можно установить как атрибут src. Затем вы можете отменить этот запрос, если вы решите отменить загрузку изображения. Это может быть сложно, если вы хотите показывать изображение постепенно.

+1

Отличная идея, но есть пара проблем, связанных с этим. Во-первых, количество переданных данных на 33% больше. (base64: 24 бит -> 32 бит). Затем (особенно в мобильных браузерах) он накладывает много давления на javascript, поскольку данные должны храниться как строка в JS, а затем он также имеет дополнительный шаг для декодирования base64. Для больших файлов (200K +) это может повредить. Но это может определенно хорошо работать в некоторых сценариях. – Amir

+0

Это хороший момент. Когда я придумал эту идею, я не думал о накладных расходах.По-видимому, было некоторое усилие в чтении двоичных файлов с использованием AJAX http://nagoon97.wordpress.com/2008/04/06/reading-binary-files-using-ajax/. Я никогда не пробовал это сам, но вы могли бы это сделать, а затем нарисовать изображение с помощью ''. –

2

У меня такая же проблема на самом деле и сделал некоторые тесты.

Я провел некоторые тесты с iframes и добился некоторого успеха. Протестировано на Firefox 3.6 и Chrome. Для тестов я использовал 9 изображений из 15Mb. С предварительной загрузкой img я несколько раз убил свой firefox (да, не так много мемуатов на этом компьютере), используя img, действие «suspend» не предотвращает загрузку изображения, если запрос запущен, с iframes действие приостановки действительно останавливает загрузку (поскольку я удалить iframe). Следующим шагом будет тестирование с XMLHttpRequests.Поскольку эта версия моего тестового кода использует поведение кэша кэширования, формируйте URL-адрес изображения, чтобы предотвратить вторую загрузку, и это также работает с запросами ajax. Но, возможно, с iframes я мог бы найти способ получить двоичные данные из загруженного изображения в iframe напрямую (с ограничением на одинаковые URL-адреса домена).

Это мой тестовый код (очень быстро на Chrome, может убить 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/

+0

Так близко, но есть проблема. По какой-то причине, когда изображение загружается в iframe, оно не доступно сразу в кеше. поэтому изображение заканчивается загрузкой дважды. вот скрипка для игры. http://jsfiddle.net/amirshim/na3UA/ Запустите fiddler2 (на ПК) и посмотрите, как изображение запрашивается дважды. Если вы отключите 'use_unique_name', вы увидите, что изображение кэшируется после первого загрузки всей страницы. – Amir

+0

Я создал новый вопрос, чтобы попытаться решить эту проблему: http://stackoverflow.com/questions/4981229/image-not-loading-from-cache-after-its-loaded-in-an-iframe – Amir

+0

на скрипке Например, я не вижу, где вы устанавливаете обратный вызов load() перед установкой атрибута src и после вставки iframe. Таким образом, вы можете вызвать это событие загрузки сразу после загрузки «about: blank» или такого, например, пустого источника базы iframe. – regilero

Смежные вопросы