防止 src 改变时大图闪烁

7

我遇到了一个关于大图片闪烁的问题。 在我的 body 中有5张图片:

<img id="img1" src="img1.png" width="250">
<img id="img2" src="img2.png" width="250">
<img id="img3" src="img3.png" width="250">
<img id="img4" src="img4.png" width="250">
<img id="img5" src="img5.png" width="250">

当我使用jQuery UI拖动其中一个时,所有的图片都会改变它们的src,在拖动结束时也是如此。
function dragStart() {
        $('#img2').attr('src','newimg2.png');
        $('#img3').attr('src','newimg3.png');
        $('#img4').attr('src','newimg4.png');
        $('#img5').attr('src','newimg5.png'); }

非常好,但我需要使用大尺寸的图片(2000 x 2000像素),因为所有的图片都可以被点击,然后它们会动画到视口的全尺寸,这样它们就不会出现像素化。

$this.animate(
                { width: 1800, top: -650, left: -250 }, 

                {
                    duration: 4000,
                    easing: 'easeOutElastic'
                }) 

我认为由于每个图像的大小,它们会闪烁。你们中有没有人有想法如何防止这些图像在同时更改所有 src 时闪烁?

感谢您的努力。


预加载图片,这样浏览器就不必在那时下载它们。有很多现有的图像预加载教程。 - Kevin B
你需要预加载图片,这样它们就会被缓存,当你更改src时就不会闪烁了。 - Pete
但是有一件事我真的不明白,如果我已经将它们拖拽过了,为什么它们还在闪烁呢?这难道不意味着它们全部都已经加载完了吗?这是因为我忘记预加载它们了! - supersize
在这种情况下,你可能会看到浏览器平滑缩小图形的结果。闪烁是什么样的?图片消失和重新出现吗?它变得像素化然后又不像素化了吗? - Kevin B
它很快地隐藏,然后出现新的! - supersize
这仍然听起来像是一个预加载问题,但也可能只是因为它太大了,需要一点时间从缓存中检索。 - Kevin B
4个回答

5
你要做的关键是预加载,但你需要仔细考虑如何实现。
预加载涉及将图像放在屏幕外但仍在DOM中的标签中加载。这会将图像缓存在本地,这意味着下次如果再次使用相同的源,则会从缓存中提取而不是向服务器查询图像(因此不会出现闪烁)。
预加载图像很简单:
(new Image()).src="mysource.png";

您需要考虑的是何时加载图像。如果一开始就全部加载,会占用大量带宽。如果在单击时加载,则会出现缓冲问题。

您可以使用img标签上存在的onload事件来检查图像是否已加载,如有必要,可以将其包装在jQuery中,具体操作如下:

var i = new Image();
i.onload = function() {
  console.log("Loaded");
}
i.src = "mysource.png";

感谢Robin Leboeuf提供简洁的Image()表单。

@KevinB:谢谢,我不知道这个!我以为你必须通过将其附加到DOM来强制浏览器呈现图像以强制加载。 - Sébastien Renauld
1
哦,左边-99999?这没有任何意义。你也可以使用<div style="display: none;"><img src="" /></div>... - Ron van der Heijden
@Bondye:已更改。现在满意了吗? - Sébastien Renauld
1
@SébastienRenauld 在设置src之前绑定加载事件,否则在IE中无法捕获加载事件,因为它在缓存图像上触发得太快了。 - Kevin B
感谢你的回答。图片仍然在闪烁,我想上面被选中的答案就是问题所在! - supersize
显示剩余3条评论

5
您描述的问题对我来说并不像是预加载问题。
因为当您开始移动它时,预加载会发生在从服务器加载另一张图片时。但是,就像我读到您的问题时,您正在移动包含图像的DOM对象中的SRC。
这很可能是浏览器问题,因为它必须将您的图像从2k x 2k缩小到100 x 100。这是一些昂贵的插值运算。因此,您的主要问题可能是您提到的图像大小。
即使预加载也没有用,因为您仍然会遇到同样的问题。
在我看来,您应该有两个版本的图像:一个小的(您想拖动的大小)和一个大的,您想显示的。大的可以自动在后台加载或按需加载,当用户点击图像时。在Web上,通常会使用平滑动画将小图像缩放到屏幕大小,并开始在后台预加载。当预加载完成时,替换全屏图像以消除像素效果。
希望我表达清楚了。

多谢你,那应该就是问题了,因为所有的图片都已经加载完毕了,但它仍然在闪烁!非常好的观察和思考,感谢你 :) - supersize

4
您可以使用以下函数预加载您的图像:
 function imagesPreload(){
     var imgArray = new Array("path/to/img1.jpg", "path/to/img2.jpg", "path/to/img3.jpg");
     for (var i=0; i<imgArray.length; i++) {
         (new Image()).src = imgArray[i];
     }
 }

1
一个问题,我不能简单地通过在主体中创建具有显示为无的div来预加载我想要的图像吗? - supersize

0
请查看注释。您应确保在显示图像之前加载它们。这称为预加载,可以通过具有所需SRC的隐藏图像(不使用display:none而是将它们放置在屏幕外)来实现。
编辑:请参阅@Sebástien的更详细的答案!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接