Рассмотрим следующий (хрупкий) код 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 = '...';