BPG 看起来确实很有希望。如果您想<img>
随时从任何来源检测元素的添加,您可以使用MutationObservers。如果您不了解它们,它们是异步的,在文档中记录所有 DOM 突变的子集,并允许回调立即处理这些突变,而不是像 DOM 事件那样同步处理。因此,如果您在脚本中创建或更改大量图像的来源,观察者将等到您的脚本完成,然后一次性处理所有新图像(因此回调中的循环)。
以下假设您有一个名为doSomethingToDecode(img)
(对不起,我现在不打算提供帮助)的函数,它src
用(很可能)生成的 PNG 替换 img 的 。它可以异步执行此操作,这不是问题。src
此外,只要生成的替换不以“.bpg”结尾,您就不需要在交换图像时停止观察图像。
当您在<img>
任何地方添加后代(以及其他元素,但它会忽略这些)时,第一个观察者会做出反应;不幸的是,在一般情况下不可能对其进行太多优化。它必须遍历突变列表,然后是每个突变的新节点列表,因此是那些嵌套for
循环。但
imgObs=new MutationObserver(
function(mutations){
for(var i=0, m; m=mutations[i]; i++) if(m.addedNodes.length)
for(var j=0, img; img=m.addedNodes[j]; j++) if(img.localName=="img"){
if(img.src && /\.bpg$/.test(img.src))
doSomethingToDecode(img)
srcObs.observe(img, srcOptions)
}
}
)
当您更改src
元素的属性时,其他观察者会做出反应,并且应该只观察<img>
元素(为了获得最佳性能,它没有故障保护,以防您让它观察其他元素,所以不要)。
srcObs=new MutationObserver(
function(mutations){
for(var i=0, m; m=mutations[i]; i++){
var img=m.target
if(img.src && /\.bpg$/.test(img.src))
doSomethingToDecode(img)
}
}
)
还要把它放在手边,每次我们开始观察新图像时都需要它:
var srcOptions={childList:false, attributes:true, attributeFilter:["src"]}
您还可以让观察者对<img>
元素的删除做出反应以停止观察它们,并释放任何与解码相关的资源,但希望浏览器至少足够聪明,可以停止观察应该被垃圾收集的元素(未经测试!) .
在加载 HTML 后运行它(不要等待带有图像和 CSS 等的整个页面)。注意:这是使用 DOM 级别 0document.images
集合。非常老派,但它正在做我们想要的非常有效和简洁的事情,那为什么不呢?
所以首先你用 bpg 源解码现有<img>
的 s,然后观察它们的src
变化:
for(var i=0, img; img=document.images[i]; i++){
if(img.src && /\.bpg$/.test(img.src))
doSomethingToDecode(img)
srcObs.observe(img, srcOptions)
}
然后这告诉第一个观察者对整个文档中的内容做出反应<body>
;不幸的是,没有tagNameFilter
参数可以本地过滤掉非<img>
childList 突变。
imgObs.observe(document.body, {subtree:true, childList:true, attributes:false})