首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加载bpg图像:兼容、简单和高效的技术

加载bpg图像:兼容、简单和高效的技术
EN

Stack Overflow用户
提问于 2014-12-21 10:07:37
回答 2查看 1.6K关注 0票数 18

图片的解码是在浏览器中使用JS完成的,这意味着它可以立即使用,而无需等待浏览器采用。总体而言,这似乎是一个好主意,用一些CPU时间来换取更快的下载速度通常是一个可行的折衷方案。

换出图像的used here技术是,在window.load上,遍历document.images,找到任何src属性包含以".bpg“结尾的URL的地方,并将其替换为画布。

然而,这绝对不是解决问题的唯一方法,我看到了这种技术的一些缺点,包括: a)画布和图像的布局规则不完全相同-例如,在画布上设置宽度属性意味着img和画布上的一些不同的东西,b)至少在Chrome中,缩小的图像和画布的缩放方式是不同的。

理想情况下,更好的解决方案将满足以下要求:

  • 试图不在内存中复制任何不必要图像数据(而且也不会不必要地使用比必要的更多的CPU -与本机图像处理相比,在JS中解码已经需要很多)
  • 具有尽可能多的浏览器兼容性
  • 使用标签而不是(不是必需的,但似乎是一种简单的方式来处理文档加载时的图像,但也包括稍后添加到文档中的图像(例如,响应用户activity)
  • Still简单易用( bellard.org上的现有技术当然很容易使用integrate)
  • EDIT:,使用web workers在不阻塞页面的情况下解码图像也是一种潜在的好方法。

我想到的一些相关工具包括data:和blob: urls。

谁有使用这种“更好”技术加载BPG的工作代码示例?( Fabrice在他的示例中使用的方式并不坏,当然方法也有权衡之处,但我认为推广使用可能会更好。)

EN

回答 2

Stack Overflow用户

发布于 2015-02-20 08:13:12

BPG看起来确实很有前途。如果您想要在任何时间、从任何来源检测<img>元素的添加,可以使用MutationObservers

下面假设您有一个名为doSomethingToDecode(img)的函数(抱歉,我现在不会对此提供帮助),它将img的src替换为(很可能)生成的PNG。它可以异步地做到这一点,这不是问题。此外,只要生成的替换不以".bpg“结尾,您就不需要在交换其src时停止观察图像。

当您在任何地方添加<img>后代(以及其他元素,但它忽略了这些元素)时,第一个观察者将做出反应;不幸的是,在一般情况下不可能对其进行太多优化。它必须遍历突变列表,然后遍历每个突变的新节点列表,因此会出现嵌套的for循环。但

代码语言:javascript
复制
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>元素(为了获得最佳性能,它没有故障保护措施,以防您让它观察其他元素,所以不要这样做)。

代码语言:javascript
复制
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)
        }
    }
)

另外,把这个放在手边,我们每次开始观察新图像时都会用到它:

代码语言:javascript
复制
var srcOptions={childList:false, attributes:true, attributeFilter:["src"]}

你也可以让一个观察者对<img>元素的移除做出反应,然后停止观察它们,并释放任何与解码相关的资源源,但希望浏览器至少足够聪明,停止观察应该被垃圾收集的元素(而不是测试!)。

在加载HTML后运行此程序(不要等待整个页面都有图像和CSS等)。注意:这使用的是DOM level 0 document.images集合。非常老派,但它做的正是我们想要的,非常高效和简洁,所以为什么不见鬼呢?

因此,首先使用bpg源代码解码现有的<img>,然后观察它们的src变化:

代码语言:javascript
复制
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突变。

代码语言:javascript
复制
imgObs.observe(document.body, {subtree:true, childList:true, attributes:false})
票数 2
EN

Stack Overflow用户

发布于 2015-02-21 05:45:09

向图像添加错误事件处理程序。在Chrome 40上,当图像丢失或浏览器不知道如何显示时会触发:

代码语言:javascript
复制
<script>
var errors = [];
function fallback(elt) {
    if(errors[elt.src]) return;
    // you should also extract the extension in order to test lena.bpg, lena.png, lena.jpg and not lena.bpg.png, lena.bpg.png.jpg
    errors[elt.src] = true;
    console.error('could not load image, falling back');
    elt.src = elt.src + '.png';
    // stop trying
    elt.onerror= function(){};
}
</script>
<img src="test.html" onerror="fallback(this);" width=300 height=300 />

优点:客户端没有内存/cpu使用率。缺点:需要在服务器上提供备用镜像。

我相信你可以在所有的img标签上声明一个全局错误监听器,所以这也适用于将来的图像。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27586134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档