JS实现图片预加载

网站开发时经常需要在某个页面需要实现对大量图片的浏览,如果考虑流量的话,大可以像pconline一样每个页面只显示一张图片,让用户每看一张图片就需要重新下载一下整个页面。不过,在web2.0时代,更多人愿意用javascript来实现一个图片浏览器,让用户无需等待过长的时间就能看到其他图片。

知道了一张图片的地址,需要把它在一个固定大小的html容器(可以是div等)里边显示出来,最重要的当然是需要知道这张即将显示的图片的宽和高,然后再结合容器的宽和高,按照一定的缩放比例使图片显示出来。因此,实现图片预加载就成为图片浏览器的核心功能了。

做过图片翻转效果的朋友其实都知道,要让图片轮换的时候不出现等待,最好是先让图片下载到本地,让浏览器缓存起来。这时,一般都会用到js里边的Image对象。一般的手段无非这样:
function preLoadImg(url) {
 var img = new Image();
 img.src = url;
}

通过调用preLoadImg函数,传入图片的url,就能使图片预先下载下来了。实际上,这里用到的预下载功能也和这基本一致。图片预下载下来后,通过 img的width和height属性,就能知道图片的宽和高了。但是需要考虑到,在做图片浏览器功能时,图片都是实时显示的。比如你点了显示的按钮,这个时候才会调用上边类似的代码来加载图片。因此,如果你直接用img.width的时候,图片还没有完全下载下来。因此,需要用一些异步的方法,等到图片下载完毕的时候才会再对img的width和height进行调用。

实现这样的异步方法实际上不难,图片的下载完毕事件也很简单,就是简单的onload事件。因此,我们可以写出下面的代码:
function loadImage(url, callback) {
  var img = new Image();
   img.src = url;

   img.onload = function(){ //图片下载完毕时异步调用callback函数。
     callback.call(img);   // 将callback函数this指针切换为img。
   };
}


好了,再来写一个测试用例。
function imgLoaded(){
   alert(this.width);
}
<input type="button" value="loadImage" οnclick="loadImage('aaa.jpg',imgLoaded)"/>


在firefox中测试一下,发现不错,果然和预想的效果一样,在图片下载后,就会弹出图片的宽度来。无论点击多少次或者刷新结果都一样。

不过,做到这一步,先别高兴太早——还需要考虑一下浏览器的兼容性,于是,赶紧到ie里边测试一下。没错,同样弹出了图片的宽度。但是,再点击load的时候,情况就不一样了,什么反应都没有了。刷新一下,也同样如此。www.2cto.com

经过对多个浏览器版本的测试,发现ie6、opera都会这样,而firefox和safari则表现正常。其实,原因也挺简单的,就是因为浏览器的缓存了。当图片加载过一次以后,如果再有对该图片的请求时,由于浏览器已经缓存住这张图片了,不会再发起一次新的请求,而是直接从缓存中加载过来。对于 firefox和safari,它们视图使这两种加载方式对用户透明,同样会引起图片的onload事件,而ie和opera则忽略了这种同一性,不会引起图片的onload事件,因此上边的代码在它们里边不能得以实现效果。

怎么办呢?最好的情况是Image可以有一个状态值表明它是否已经载入成功了。从缓存加载的时候,因为不需要等待,这个状态值就直接是表明已经下载了,而从http请求加载时,因为需要等待下载,这个值显示为未完成。这样的话,就可以搞定了。

经过一些分析,终于发现一个为各个浏览器所兼容的Image的属性——complete。所以,在图片onload事件之前先对这个值做一下判断即可。最后,代码变成如下的样子:
function loadImage(url, callback) {
    var img = new Image(); //创建一个Image对象,实现图片的预下载
     img.src = url;
  
    if (img.complete) { // 如果图片已经存在于浏览器缓存,直接调用回调函数
         callback.call(img);
        return; // 直接返回,不用再处理onload事件
     }

     img.onload = function () { //图片下载完毕时异步调用callback函数。
         callback.call(img);//将回调函数的this替换为Image对象
     };
};

经过这么一番折腾,总算是让各个浏览器都能满足我们的目标了。虽然代码很简单,但是却把图片浏览器中最核心的问题解决掉了,接下来你所要做的,仅仅是图片如何呈现的问题了


摘自 PainsOnline的专栏

转载于:https://www.cnblogs.com/woshikay/p/4050299.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/292680.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用sort()方法随机打乱数组

2019独角兽企业重金招聘Python工程师标准>>> 我们先看一下随机数组排序的示例&#xff0c;再来研究其中的原理。 随机数组排序示例 var numbers [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; numbers numbers.sort(function(…

Linux下部署Kubernetes+Kubesphere(一)Kubernetes基础

1.服务器规划为配置Kubesphere高可用集群&#xff0c;需要三台或三台以上机器作为Master节点&#xff0c;每台机器既可以作为Master也可以作为Worker节点。其中Master节点数量建议为单数。该示例中采用三台服务器&#xff0c;即作为Master节点也作为Worker节点&#xff0c;配置…

触发器及其应用实验报告总结_调机技巧总结: 先快后慢射胶法及其应用

戳我进入社区&#xff1a;注塑和模具人的网上家园先快后慢&#xff0c;也即先用一级快速射胶&#xff0c;射到某个设定的位置时&#xff0c;再起二级慢速射胶。这个二级起级点一般是设在射胶充型的后期&#xff0c;也即接近充型结束的位置。使用一级快速射胶&#xff0c;可以保…

汇编语言之寻址方式

&#xfeff;&#xfeff;1、内存单元和[bx]的描述 要完整地描述一个内存单元&#xff0c;需要两种信息&#xff1a;1.内存单元的地址&#xff1b;2.内存单元的长度&#xff08;即是字节单元还是字单元&#xff09;。 如&#xff1a;mov ax, [2a78] 表示将一个内存单元中的数…

命名空间的使用

namespace hunan\changsha class Person{ static $namewu_han; } namespace hunan\changsha 声明命名空间&#xff0c;它的作用包括方法&#xff0c;类名&#xff0c;常量&#xff0c;这三者都统称为元素 当在程序里使用元素的时候&#xff0c;默认在当前的命名空间里找该元素…

使用 dotnet-monitor 在 Kubernetes 中收集 .NET metrics

使用 dotnet-monitor 在 Kubernetes 中收集 .NET metricsIntrodotnet-monitor 是微软推出的一个帮助我们诊断和监控 .NET 应用程序的工具&#xff0c;在 Kubernetes 中我们可以让 dotnet-monitor 作为 sidecar 运行&#xff0c;无侵入地监控 .NET 应用&#xff0c;今天我们就来…

DOM 事件深入浅出(二)

在DOM事件深入浅出&#xff08;一&#xff09;中&#xff0c;我主要给大家讲解了不同DOM级别下的事件处理程序&#xff0c;同时介绍了事件冒泡和捕获的触发原理和方法。本文将继续介绍DOM事件中的知识点&#xff0c;主要侧重于DOM事件中Event对象的属性和方法。 那么什么是DOM事…

arcgis 分区 属性值_ArcGIS制图之Maplex自动点抽稀

制图工作中&#xff0c;大量密集点显示是最常遇到的问题。其特点是分布可能不均匀、数据点比较密集&#xff0c;容易造成空间上的重叠&#xff0c;影响制图美观。那么&#xff0c;如果美观而详细的显示制图呢&#xff1f;主要原理Maplex中对标注有很好的显示控制&#xff0c;一…

学术造假导致导师自杀,后将这段学术丑闻经历出书贩卖,一年收入上百万......

全世界只有3.14 % 的人关注了爆炸吧知识本文转自募格学术2020年2月11日&#xff0c;小保方晴子又被撤回了一篇研究论文。Tissue Engineering Part A撤稿给出的原因是&#xff1a;通过哈佛医学院正式调查后&#xff0c;无法确实其实验结果的准确性&#xff0c;尽管作者本人坚持已…

汇编语言之数据处理的2个基本问题

&#xfeff;&#xfeff;1、bx、si、di和bp Bx、si和di这3个寄存器我们已经学过了&#xff0c;现在进行一下总结&#xff0c;并学一下bp。 1&#xff1a;在8086CPU中&#xff0c;只有这4个寄存器可以用在[…]中来进行内存单元的寻址。比如&#xff0c;下面的指令都是正确 的…

js(jQuery)获取时间的方法及常用时间类

获取JavaScript 的时间使用内置的Date函数完成 var mydate new Date();mydate.getYear(); //获取当前年份(2位)mydate.getFullYear(); //获取完整的年份(4位,1970-????)mydate.getMonth(); //获取当前月份(0-11,0代表1月)mydate.getDate(); //获取当前日(1-31)mydate.getD…

phalcon: 缓存片段,文件缓存,memcache缓存

几种缓存&#xff0c;需要用到前端配置&#xff0c;加后端实例配合着用 片段缓存&#xff1a; public function indexAction(){//渲染页面$this->view->setTemplateAfter(common);//缓存片段 //前端配置$frontcache new \Phalcon\Cache\Frontend\Output(array(&q…

nvm用标准sata ahci码_能者多劳!让NVMe固态硬盘做系统盘的同时,加速SATA数据盘...

不知不觉当中&#xff0c;固态硬盘已经取代机械硬盘成为主流。越来越多的玩家已经淘汰机械盘&#xff0c;使用NVMeSATA的固态硬盘高低搭配。既然是高低搭配&#xff0c;就一定会有性能差距&#xff0c;是否能从NVMe固态硬盘中划分出一小部分空间来给SATA固态硬盘加速&#xff0…

天了噜!定义static字段还有顺序要求?

前言前段时间&#xff0c;发现一个bug&#xff0c;代码结构类似下面的示例。你能说出这段代码的正确返回结果吗&#xff1f;class Program {private static int a1 a2;private static int a2 Init();private static int Init(){return 123;}static void Main(string[] args){…

汇编语言之转移指令和原理

&#xfeff;&#xfeff;1、引言 可以修改IP&#xff0c;或同时修改CS和IP的指令统称为转移指令。概括地讲&#xff0c;转移指令就是可以控制CPU执行内存 中某处代码的指令。 8086CPU的转移行为有以下几类&#xff1a; 1. 同时修改CS和IP时&#xff0c;称为段间转移&#…

【高德地图开发2】---配置工程

1.从网站下载开发包并解压。 3D地图包解压后得到&#xff1a;3D地图显示包“Android_Map_2.x.x.jar ”和文件夹“ armeabi ”&#xff08;以 V2.2.0为例&#xff0c;含 - libamapv302.so 和 libmapv302ex.so 文件&#xff09;。2D地图包解压后得到&#xff1a;2D地图显示包“An…

antd option宽度自适应_建议收藏:Axure手机自适应教程

hello&#xff0c;我又来啦&#xff0c;今天和大家分享用axure怎么做自适应&#xff0c;也就是说&#xff0c;我们做app端的作品时&#xff0c;怎么在不同的手机尺寸&#xff0c;显示最佳的样式。那么这期的话&#xff0c;我会以一个游戏的案例来展开&#xff0c;所以比较好玩。…

svn之Previous operation has not finished; run ‘cleanup‘ if it was interrupted解决办法

今天提交代码的时候出现了 Previous operation has not finished; run cleanup if it was interrupted 解决办法&#xff1a; 点击项目右键&#xff0c;然后点击乌龟svn&#xff0c;然后再去点击 clean up 就可以解决了 &#xfeff;&#xfeff;