使用临时gif图像预加载背景图像

时间:2012-08-11 15:02:45

标签: javascript

我有几个带背景图片的div。我想知道如何使用gif图像预加载那些背景图像,因为一些背景图像非常大。执行以下操作无效:

HTML:

<div id="glykopeels" onload="loadImage()">Glykopeels Content</div>
<div id="facials" onload="loadImage2()">Facials Content</div>

CSS:

#glykopeels{
        background: #ebebeb url(http://lamininbeauty.co.za/images/products/preloader.gif) no-repeat top right;
        background-size: contain;
    }
#facials{
    background: #ebebeb url(http://lamininbeauty.co.za/images/products/preloader.gif) no-repeat top right;
    background-size: contain;
    }

JS:

function loadImage(){
        document.getElementById('glykopeels').style.background = '#ebebeb url(http://lamininbeauty.co.za/images/products/glykopeel.jpg);';
    }
function loadImage2(){
        document.getElementById('facials').style.background = '#ebebeb url(http://lamininbeauty.co.za/images/products/facial.jpg);';
    }

我想在onload函数中定义该元素的不同ID,并为该新ID定义css是另一种可能性吗?因此只更改onload函数中该元素的id?

谢谢

3 个答案:

答案 0 :(得分:5)

首先: div没有onload属性。 编辑:请阅读以下评论,非常有趣!

其次,你应该在引号之间放置url(如果需要,可以转义它们):url('http://lamininbeauty.co.za/images/products/facial.jpg')

第三,没有名为preloader.gif的图片,但是有一张名为loader.gif的图片,所以我使用了那张图片来修复&#39;你的css部分是我在底部的jsfiddle演示链接中的解决方案。

在SO的服务器移动过程中,我为您编写了一个简单的自定义功能,可以完全您想要的功能。
经过测试 IE6 和FF12。
要对此进行测试:请清除您的浏览器缓冲区,否则您无法查看它(它会变得太快),因为图像可能会在第二个视图上缓存(同样,完美的目标)!

JavaScript:

var repBg=function(a, t){ t=t||'*';  // by GitaarLAB
        var c=document.getElementsByTagName(t), i=c.length, r=[];
        while(i--){if (c[i].getAttribute(a)){r.push(c[i]);}} c=r; i=c.length;
        repBg.exec=function(){
            c[this['data-i']].style.background="#ebebeb url('"+this.src+"') no-repeat top right";
        };
        while(i--){ if (c[i].getAttribute(a)) {
            r=new Image();
            r.onload=repBg.exec;
            r['data-i']=i;
            r.src=c[i].getAttribute(a);
        }}  
};

// one could run repBg onload, but better to run it when the image has actually loaded, see html!
// window.onload=function(){  repBg('data-bg_img','div');  };

在您的身体中:添加属性&#39; data-bg_img&#39; (根据html5约定,以数据开头 - )到你想要使用这种技术的元素,并让它包含你的背景网址,如下所示:

<div id="glykopeels" data-bg_img="http://lamininbeauty.co.za/images/products/glykopeel.jpg">Glykopeels Content</div>

&#39;可选&#39;在你的身体初始化:

<!--
trigger the replace background function when the loader image has actually loaded!
rewriting the onload with nothing to prevent infinite loop in IE6 (and greater?) !!
-->
<img src="http://lamininbeauty.co.za/images/products/loader.gif" style="display:none;" onload="this.onload=null; repBg('data-bg_img','div');">

<强>手动/解释:
图像有一个onload-event,所以我们在html(底部)放置一个加载图像,它会触发它自己的onload-event,一旦浏览器实际上就调用repBg()下载了这个loading-image!

函数repBg()最多需要2个参数:

  • 包含应选择的属性的第一个必填字符串
  • 第二个可选参数可以定义标记名(限制第一个参数)。

调用后,函数repBg()将在主体中搜索符合第二个参数或*的elementTagNames,然后使用第一个参数对其进行过滤。
对于保留在过滤的htmlObjectCollection中的每个htmlObject,创建一个新图像(不附加到正文),其中htmlObject的属性值(url)对应于函数的第一个参数作为图像源,与htmlObjectCollection一起引用id(属性data-id)以供参考 一旦这些图像加载,它们就会触发onload事件:调用repBg的{​​{1}}方法,用新的(大)背景图像替换引用的htmlObject的背景(和你的其余部分)。为了进一步模块化,您可以扩展该功能。

最后,注意:背景图片加载,以便它们出现在源代码中,也就是您希望工作的方式!

您可以在this fiddle: http://jsfiddle.net/epdDa/

中看到它的实际效果

更新版本2:非常棒的回归!!和COPY-PASTE NOBRAIN解决方案
我的生活日光让我感到恼火,因为我的第一个解决方案没有提供优雅的后备。所以我提出了一个不同的解决方案,提供优雅的后备 还在 IE6 和FF12中进行了全面测试 它的工作原理如下:
在你的身体:简单设置你的div的课程,以预先加载&#39;并将它的style-attribute设置为它应该正常加载的backgroundimage。像这样:

exec

这很容易吗? 然后将以下脚本放在HTML的HEAD(这很重要)中:

<div id="facials" class="preload" style="background: #ebebeb url('http://lamininbeauty.co.za/images/products/facial.jpg') no-repeat top right;">Facials Content</div>

<强>解释
它花了我一整夜..但我找到了办法 如果启用了javascript,函数repBg将通过向文档头(它所在的位置,注意将它放在最后一个css脚本之后)写一个额外的样式块来开始,它为所有元素设置loader-background-image上课&#39; preload&#39; (从而在页面加载时显示加载图像) 如果加载了加载图像的加载测试图像并加载了窗口(以获取正文中的所有元素),那么它与版本1基本相同。只是这次我们从中获取并匹配来自的URL元素的样式 - 属性和onload随后清空元素的样式属性。

由于此功能自动执行并使用类似于版本1的版本(如上所述)覆盖自身,因此您只需在功能的最后一行调整参数&#39; repBg&#39;。
请注意:在其初始状态// getElementsByClass original by dustin diaz, modified by GitaarLAB document.getElementsByClassName=document.getElementsByClassName||function(searchClass,node,tag) { var classElements = [], i=0, j=0; if (!node){node = document;} if (!tag){tag = '*';} var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp('(^|\\\\s)'+searchClass+'(\\\\s|$)'); for (; i < elsLen; i++) { if ( pattern.test(els[i].className) ) { classElements[j] = els[i]; j++;} } return classElements; }; var repBg=(function(n,u,p,a,i,r){ // by GitaarLAB window.onload=function(){repBg(1);}; i=new Image(); i.onload=function(){this.onload=null; repBg(2);}; document.write("<style>."+n+"{background:"+p+" url("+u+") "+a+ " !important; background-size: contain !important;}"+ "</style>"); i.src=u; r=0; return function(t){ r=r+t; if(r>2){ var c=document.getElementsByClassName(n), i=0, l=c.length, s; repBg.exec=function(){ document.getElementById(this['data-id']).className=''; }; for(;i<l;i++){ r=new Image(); r.onload=repBg.exec; r['data-id']=c[i].getAttribute('id'); s=c[i].getAttribute('style'); try { // sane browsers r.src=s.match(/url\('?([^'"]*)'?\)/i)[1]; } catch(e) { // <IE8 r.src=s.cssText.match(/url\('?([^'"]*)'?\)/i)[1]; } } } }; })('preload','http://lamininbeauty.co.za/images/products/loader.gif','#ebebeb','no-repeat top right'); 中最多接受4个参数:className,Url,cssPrepend和cssAppend。

要查看它的实际效果(请勿忘记按照说明清理浏览器缓冲区),
点击this fiddle: http://jsfiddle.net/epdDa/1/

无论谁使用此功能,如果你相信我,我将不胜感激!


<强>更新
额外的解释和评论的答案。

两个版本之间的主要区别
从技术上讲,两个版本都使用几乎相同的技术,因此没有真正的区别。

  • 对于版本1,javascript是 ISNEDED 使页面工作的粘合剂,但是在有效的真实xhtml和普通html中工作。
    但是,关闭javascript的用户将获得非功能性网站(仅显示loading-gif)。请注意,所有其他当前答案,包括您前往的方向,都会遇到此问题!
  • 对于版本2,javascript只是增强页面交互的方式(网站应该编码的方式),但只适用于html(或无效的xhtml)。
    但是,这应该确保关闭javascript的人仍然看到正常运行的页面。 IE:javascript NOT NEEDED 正确显示网站。这个概念被称为“优雅的后备”&#39;或者&#39;优雅地退化&#39;。我对第2版的投票没有。
    额外奖励:此路径为您提供普通的香草验证和SEMANTIC HTML,因为您使用古老的可信赖的在线风格,ID和类。我对第2版的投票没有2

为什么我选择使用内联css?为什么必须&#39;你使用内联css来实现这个目的吗?
首先,我花了小时来避免内联css。 (我没有松开它们,我学会了不起作用的方式,同样有用)。接下来,我想再次指出所有当前的答案,包括你要去的方向,将实际的背景图像url与css分开,而在css中,你分别在每个div上设置加载器图像,更有意义。版本2只使用可配置的类名。

文档“HEAD”中的readingwriting个css块都是一团糟...... 我是否提到了链接的外部css文件.. ??

在我看来,所有这些都需要这么多额外的代码和cpu-cycles以及在每个页面加载上阻塞/暂停浏览器,以便核心原则工作:最后一个有效的css规则适用。因此,加载图像会尽快显示,因为它是页面加载时指定的背景图像,正是人们想要的这种功能。如果元素不再是“预加载”的一部分。类?右:它的内联css生效,更新速度与浏览器可以渲染一样快(如果图像已经加载)。好的。

因此,如果您通过简单地使用repBg来牺牲(真实)xhtml支持,那么目前仍然证明这是最好的&#39;要走的路(你可以在之前的2个链接中阅读)。它仍然适用于外部链接的CSS。我的第三次(KISS-)投票支持第2版。

我对第2版的第四次投票是因为:document.write函数已准备好让它repBg方法(=函数)&#39;已升级&#39;所以你只能拿出预载&#39;来自班级的价值&#39;值列表。一个简单的replace()就足够了(目前没有速度)。

我对第2版的第五次也是最后一次投票是因为它优雅的后备设置,修复或阻止某些浏览器使用额外的“spice”也相对容易。

最后,关于速度:我认为版本2总是让人感觉更快:onload-image的显示速度几乎与浏览器可以获取它一样快(好像这个额外的css总是在那里开始),加载动画加载snappy因为:他们的负载已经在头部启动,并且浏览器不会下载被覆盖的图像,直到该函数调用。此外,他们看起来互动而不会分心。但..当加载实际背景图像和css更新时:bam!图像在那里,没有从上到下扫描的效果&#39;。这种效果让人觉得很难受。实际上,我已经说服了,并且会对图片中的图像进行调整,以获得快照和增加感知的初始页面加载量。注意,这是我的观点。你的里程可能会有所不同哈哈。

祝你好运! (如果你喜欢/使用这个想法/功能请投票,谢谢!)

答案 1 :(得分:2)

1)div元素没有load个事件,此事件仅适用于正文,图片和脚本标记。 编辑:像@icktoofay所指出的那样,在HTML规范中,所有元素都存在onload,但主流浏览器尚未支持此功能。

2)将此脚本标记放在html页面的末尾

<script>
    function loadImages() {
        var glykopeels = document.getElementById('glykopeels');
        var facials = document.getElementById('facials');

         glykopeels.style.backgroundImage = 'url(http://lamininbeauty.co.za/images/products/glykopeel.jpg)';
         facials.style.backgroundImage = 'url(http://lamininbeauty.co.za/images/products/facial.jpg)';

3)你可以像你一样设置style.background,但不要将;放在字符串的末尾,否则它将无效。

小提琴:http://jsfiddle.net/pjyH9/

修改

似乎加载程序图像没有显示,因为一旦浏览器收到新图像的第一个字节,它就会从后台删除loader.gif。我们采取另一种方法。 这是一个将图像加载到缓存的函数,然后 - 当加载图像时 - 将图像设置为具有指定id的元素的背景。

function loadImageToBackground(elementId, imageUri) {
    var img = new Image();
    img.onload = function() {
       document.getElementById(elementId).style.backgroundImage = "url('" + imageUri +   "')";
    };
    img.src = imageUri;   
}

您想要加载器的元素:

// past the element id and the image url to the function
loadImageToBackground('glykopeels', ​'http://image....');

我很确定这会奏效。函数loadImageToBackground执行基本工作,如果需要,可以扩展和添加更多功能。

这里有一个工作示例:http://jsfiddle.net/pjyH9/19/ (它加载2个图像,每个1.5mb,因此您可以看到加载器正在运行)。

答案 2 :(得分:1)

我认为你要做的是让背景图像在加载后切换到大的JPG图像。你应该能够适应这样的事情为你工作:

<html>
  <head>
    <title>Image Load Test</title>
    <script type="text/javascript">
      function loadImage(preloader, imageDiv) {
        document.getElementById(imageDiv).style.background = '#ebebeb url('+preloader.src+') no-repeat top right';
        // I think resetting the background property also resets backgroundSize.
        // If you still want it 'contained' then you need to set the property again.
        document.getElementById(imageDiv).style.backgroundSize = 'contain';
      }
    </script>
    <style type="text/css">
      #testImage {
              background: #ebebeb url(small-image.gif) no-repeat top right;
              background-size: contain;
      }
      #preloads { display: none; }
    </style>
  </head>
  <body>
    <div id="testImage">Some Content</div>
    <div id="preloads">
      <img src="full-image.jpg" onload="loadImage(this, 'testImage')">
    </div>
  </body>
</html>

这里的主要区别在于我正在<img>中预加载JPG图像,该<div>隐藏在display: none onLoad属性中以隐藏它。我不确定div事件究竟对onLoad做了什么,但我很确定这不是你想要的。将img事件放在background-size元素中会导致事件在图像完全加载后触发,我相信 你想要的。

编辑 我在JavaScript中添加了一行来重置{{1}}属性。如果那不是你想要的,那就忽略那个部分。