Phr*_*ogz 71 html javascript image data-uri
考虑以下(脆弱的)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!'); };
Run Code Online (Sandbox Code Playgroud)
问题
onload
调用回调(在src更改后设置)?实验测试
我创建了一个具有类似代码的简单测试页面.在Safari我的第一次测试,都是由本地打开HTML网页(file:///
URL),并从我的服务器加载它,结果显示一切工作:高度和宽度是正确的,在画布上绘制的作品,并且在onload
还火.
在Firefox v3.6(OS X)中,启动浏览器后加载页面显示设置后高度/宽度不正确,drawImage()
失败.(然而,onload
处理程序会触发.)然而,再次加载页面会在设置和drawImage()
工作后立即显示宽度/高度.Firefox似乎将数据URL的内容缓存为图像,并在同一会话中使用时立即可用.
在Chrome v8(OS X)中,我看到与Firefox相同的结果:图像不能立即使用,但需要一些时间从数据URL异步"加载".
除了实验证明上述哪些浏览器有效或无效之外,我真的很喜欢这些应该如何表现的规范的链接.到目前为止,我的Google-fu还没有完成任务.
安全玩耍
对于那些不明白为什么上面可能有危险的人,要知道你应该使用这样的图像是安全的:
// 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 = '...';
Run Code Online (Sandbox Code Playgroud)
Phr*_*ogz 52
由于没有一个目前尚未发现这是怎么任何规格应该的行为,我们将不得不与它是如何满足并表现.以下是我的测试结果.
| 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** ------------+-----------------------------+-------------------------------------
综上所述:
onload
事件.onload
在设置之后设置处理程序src
并期望调用它.如果有人能找到讨论这个的规格,我会乐意接受他们的回答.
在将控制权交还给浏览器的渲染引擎后,测试报告true
在FF 4b9和Chromium 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);
Run Code Online (Sandbox Code Playgroud)
更新:是的,我理解这个"答案"更像是一个评论,但只是想指出来.经过测试,我得到了可重复的结果:
setTimeout
,在这两种浏览器中,我false
第一次打开页面时true
才会遇到F5.明确清除缓存false
后,重新加载后再说一遍.setTimeout
宽度/高度测试总是evualuates true
.在这两种情况下,只有在重新加载页面后,图像才会第一次显示.