и только ссылка на изображение в обратном вызове будет работать. Мой вопрос заключается в том, существуют ли спецификации, описывающие, как это должно работать.

отрим следующий (хрупкий) код JavaScript:

var img = new Image;
img.src = "data:image/png;base64,..."; // Assume valid data

// Danger(?) Attempting to use image immediately after setting src
console.log( img.width, img.height );
someCanvasContext.drawImage( img, 0, 0 );

// Danger(?) Setting onload after setting src
img.onload = function(){ console.log('I ran!'); };

Вопросы)

Должны ли ширина и высота изображения быть правильными сразу?Должен ли холст рисовать сразу?Еслиonload обратный вызов (установленный после изменения src) будет вызван?

Экспериментальные испытания
Я создалпростая тестовая страница с похожим кодом. В Safari мои первые тесты, оба, открывая HTML-страницу локально (file:/// url) и загрузив его с моего сервера, показал, что все работает: высота и ширина верны, холст работает,а также onload также пожары.

В Firefox v3.6 (OS X) загрузка страницы после запуска браузера показывает, что высота / ширина неверна сразу после настройки,drawImage() выходит из строя. (Theonload однако, обработчик срабатывает.) Загрузка страницы снова, однако, показывает правильность ширины / высоты сразу после установки, иdrawImage() работает. Похоже, что Firefox кэширует содержимое URL-адреса данных в виде изображения и сразу же получает его при использовании в том же сеансе.

В Chrome v8 (OS X) я вижу те же результаты, что и в Firefox: изображение не доступно сразу, но требуется некоторое время для асинхронной «загрузки» из URL-адреса данных.

В дополнение к экспериментальному доказательству того, что браузеры вышеупомянутые работают или не работают, я действительно хотел бы ссылки на спецификации о том, как это должно вести себя. Пока что мой гугл-фу не справился с этой задачей.

Играя Безопасно
Для тех, кто не понимает, почему вышеизложенное может быть опасно, знайте, что вы должны использовать изображения, подобные этим, чтобы быть в безопасности:

// First create/find the image
var img = new Image;

// Then, set the onload handler
img.onload = function(){
  // Use the for-sure-loaded img here
};

// THEN, set the src
img.src = '...';
 Alston09 дек. 2012 г., 10:37
@phrogz Привет, Phrogz, эта функциональность очень важна для меня; однако в браузере Android (теперь последняя версия) назначение dataURL источнику изображения просто не может работать должным образом даже с помощью метода «Безопасная игра». Не могли бы вы дать мне больше предложений?
 Phrogz24 янв. 2011 г., 03:11
@mP Да, это действительно так; Я отредактировал свой вопрос, чтобы прояснить это за 5 минут до вашего комментария :) Однако это не лишает законной силы вопрос. Если предположить, что поведение в Chrome и FF допустимо, а не ошибка, то на самом деле жизненно важно, чтобы это было безопасно.
 mP.23 янв. 2011 г., 23:43
Разве не безопаснее предположить, что нет, прокачать время ожидания и продолжить после того, как браузер получит возможность перерисовать себя?
 Pekka 웃23 янв. 2011 г., 22:37
Вам определенно нужно установитьonload перед установкойsrc, Но если событие load иногда срабатывает в текущем созвездии, то установка URI «data» действительно является асинхронной, что меня удивило бы. Интересно!
 Phrogz26 янв. 2011 г., 17:46
@Pekka Смотрите мой «ответ» ниже; IE9 требует установки onload перед установкой src, но никакой другой браузер этого не делает. (!) Удивительно, действительно.

Ответы на вопрос(2)

Решение Вопроса

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

            | is image data usable right  | does onload callback set after src
            |     after setting src?      |   is changed still get invoked?
------------+-----------------------------+-------------------------------------
Safari  5   |             yes             |                  yes                
------------+-----------------------------+-------------------------------------
Chrome  8   | **no** (1st page load), but |                  yes                
FireFox 3.6 |  yes thereafter (cached)    |                                     
------------+-----------------------------+-------------------------------------
IE8         |    yes (32kB data limit)    |                  yes         
------------+-----------------------------+-------------------------------------
IE9b        |             yes             |                 **no**              
------------+-----------------------------+-------------------------------------

В итоге:

Вы не можете предполагать, что данные изображения будут доступны сразу после установки data-uri; ты должен ждатьonload мероприятие.Из-за IE9 вы не можете установитьonload обработчик после установкиsrc и ожидать, что это будет вызвано.Рекомендации в«Играя безопасно» (из вопроса выше) являются единственным способом обеспечения правильного поведения.

Если кто-то сможет найти спецификации, обсуждающие это, я с радостью приму их ответ.

 J Trana09 дек. 2013 г., 04:23
Спасибо за исследование, которое вы сделали здесь. Я боролся с возможностью принудительного использования такого поведения для автономного веб-приложения, где мне нужно отчитываться, используя canvas, поэтому я немного углубился в это. Живая спецификация WHATWG фактически вызывает кэшированный случай как синхронный, а не кэшированный случай как асинхронный. Проверьте шаг 7 в разделе src спецификации, найденной здесь:whatwg.org/specs/web-apps/current-work/multipage/..., Появляется, если изображение находится в «списке доступных изображений» документа, оно завершается синхронно, или я так его читаю.

ияхtrue в FF 4b9 и хроме 8.0.552.237. Я изменил эти части:

img.onload = function(){   // put this above img.src = …
    document.getElementById('onload').innerHTML = 'yes';
};
img.src = img_src;
…
window.setTimeout(function () {   // put this inside setTimeout
    document.getElementById('wh').innerHTML = (img.height==img.width) && (img.height==128);
}, 0);

Обновить: Да, я понимаю, что этот «ответ» больше похож на комментарий, но просто хотел указать на это. И после тестирования я получаю воспроизводимые результаты:

безsetTimeoutв обоих браузерах получаюfalse в первый раз я открываю страницу иtrue только после удараF5, После явной очистки кеша оба говорятfalse снова после перезагрузки.с участиемsetTimeout тест ширины / высоты всегда соответствуетtrue.

В обоих случаях изображение не отображается в первый раз, только после перезагрузки страницы.

 Phrogz23 янв. 2011 г., 22:57
Вы говорите мне, что без этих изменений вы видите «неудачи» в FF и Chromium? Мой вопрос не в том, как заставить это работать - четкоonload доsrc и только ссылка на изображение в обратном вызове будет работать. Мой вопрос заключается в том, существуют ли спецификации, описывающие, как это должно работать.

Ваш ответ на вопрос