Рассмотрим следующий (хрупкий) код 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()
завершается с ошибкой. (Однако обработчик onload
срабатывает.) Однако загрузка страницы снова показывает правильность ширины/высоты сразу после настройки и drawImage()
. Похоже, что Firefox кэширует содержимое URL-адреса данных в качестве изображения и имеет его доступное сразу же при использовании в одном сеансе.
В Chrome v8 (OS X) я вижу те же результаты, что и в Firefox: изображение недоступно сразу, но занимает некоторое время, чтобы асинхронно "загружать" с URL-адреса данных.
В дополнение к экспериментальному доказательству того, какие браузеры выше или не работают, мне действительно нравятся ссылки на спецификации того, как это должно себя вести. Пока что мой Google-фу не справился с задачей.
Воспроизведение в безопасности
Для тех, кто не понимает, почему вышеуказанное может быть опасным, знайте, что вы должны использовать изображения, подобные этому, в безопасности:
// 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 = '...';