使用base64预加载图像

时间:2012-08-15 17:56:30

标签: php javascript animation base64 preload

我为我的用户制作了一个'拖放'文件上传工具。我在13个PMG图像中创建了一个上传进度条,并使用jQuery对其进行了动画处理。如果用户只是同时删除一个或两个文件,那么这种方法很有效。但我注意到,如果用户丢弃10个文件,浏览器会对每个图像发出请求(130个请求)。有时浏览器从缓存中获取这些图像,但有时不会。所以,我的解决方案是像这样预加载图像:

function preload()
{ 
    // create object
    imageObj = new Image();

    // set image list
    images = new Array();
    images[0]="img/ProgressBarContent.png";
    images[1]="img/ProgressbarEndEffect.png";
    images[2]="img/0.png";
    images[3]="img/1.png";
    images[4]="img/2.png";
    images[5]="img/3.png";
    images[6]="img/4.png";
    images[7]="img/5.png";
    images[8]="img/6.png";
    images[9]="img/7.png";
    images[10]="img/8.png";
    images[11]="img/9.png";
    images[12]="img/percentIcon.png";
    images[13]="img/ProgressBar.png";

    // start preloading
    for(var i = 0; i < images.length; i++) 
    {
        imageObj.src=images[i];

        if(i == (images.length-1))
        {
        //preloading done, give a visual feedback and droping functionality can be activated 
        hideLoadingOverlay();
        }     
     }
 }

但这没有任何区别 所以我想我可以让PHP脚本读取我需要的图像,将它们编码为base64并将它们输出为这样的JavaScript数组:

$file= base64_encode( file_get_contents ( 'img/0.png') );
echo 'images["img/0.png"] = "data:image/png;base64,'.$file.'";';

这样我也可以将图像直接“硬编码”到我的HTML中,对吧? 我认为在JavaScript中我可以这样做:

$(".selector").attr("src", images['filename']);

这是一个很好的解决方案吗?还是有“适当的”/更好的方式?

谢谢!

编辑: 如果旧浏览器不支持此功能并不重要。这些脚本用于管理区域,仅供我认识的人使用。 (而且它们都有现代浏览器。)

3 个答案:

答案 0 :(得分:1)

更好的想法可能是确保您的Web服务器为您的映像发出适当的缓存标头,一旦您这样做,浏览器将只请求它们一次并从缓存中拉出后续请求。如果您对配置缓存设置没有任何帮助,请随时使用您使用的Web服务器对此答案发表评论,我将编辑我的答案。

此外,您可以在使用javascript加载页面时预加载所有图像,以确保浏览器在需要显示时缓存它们:

var imageObj = new Image();
var images = new Array();
images[0]="image1.jpg"
images[1]="image2.jpg"
images[2]="image3.jpg"
images[3]="image4.jpg"

for(var i=0; i < images.length; i++) {
    imageObj.src=images[i];
}

编辑,在apache2中设置缓存

您可以使用.htaccess文件在每个目录/每个文件的基础上配置这些设置,您可以阅读有关here的更多信息。基本上,您要做的是在文档根目录中创建.htaccess文件,并输入以下内容:

# cache images for 10 days
<FilesMatch "\.(ico|jpg|jpeg|png|gif)$">
  Header unset Pragma
  FileETag None
  Header unset ETag
  Header set Cache-Control "max-age=864000, public, must-revalidate"
  Header unset Last-Modified
</FilesMatch>

答案 1 :(得分:1)

IE不支持data URI方案(如果是,则是最近添加的)。

我已经解决了浏览器并不总是从缓存中获取图像的事实,因为它应该是。仔细检查您是否使用了URI的变体进行某些调用,然后检查发送的标头是否合适,并且最大年龄至少为一小时(如果不是更多)。

对于这种用途,使用pngslim或类似的方法来刮掉发送内容的每一个字节也不会对图像造成伤害。

答案 2 :(得分:1)

最好的方法是创建一个精灵,所以如果图像是10x10并且动画中有10帧,你将创建一个10x100的精灵。

然后你创建一个类,每个类偏移背景10像素。不是为每个帧加载单独的图像,而是偏移相同的图像以创建动画。

在我们的情况下,css看起来像这样:

.sprite {
    background: url('/images/sprite.png');
    display: block;
    width: 10px;
    height: 10px;
}
.sprite.frame1 {
    background-position: 0 -10px;
}
.sprite.frame2 {
    background-position: 0 -20px;
}
...

js看起来像这样:

for (i=0;i!=11;i++) {
    document.getElementById("MyElement").className = "sprite frame" + i;
}

你得到了照片。即使屏幕上有100个动画,图像也只会加载一次。