快乐前端--图片预加载

前言

正所谓金三银四五吃土,因此这些天几个前端技术群讨论最多的话题就是面试题了。某日群内讨论一道面试题:“前端如何实现大量图片预加载以及预加载进度动画进度条显示?”

恰巧本人以前jquery、zepto一把梭快乐切图的时候,写过不少形式的图片预加载动画。对于图片预加载的原理稍微了解接触过那么一点点,这里献丑一番简单写一个预加载案例,作为19年第一篇博(段)客(子)快乐一哈。

你离挨打只差一点点.png

一、利用image对象搞事情

既然是利用image对象搞事情,那肯定少不了大量的img图片。因此我从名字中包含刺激二字的网站上面扒了不少各位带妹司机热血沸腾的图片,没错就是腾讯刺激战场--各种武器图片。

武器截图.png

emmm,不皮了。我们直接进入主题内容,JavaScript当中的image对象。关于Image对象的介绍MDN上面写的, 当new Image()的时候会生成一个HTMLImageElement.

Image对象执行.png

HTMLImageElement这是什么?和我们熟悉的HTMLElement这个节点有什么不同呢?顺着上面的链接提示,我们继续顺藤摸瓜,最后发现HTMLImageElement 属于HTMLElement孩子。

HTMLImageElement.png

既然继承了HTMLElement特性,同理body元素有一个onload属性,那么同理new Image得到对象也同样拥有onload属性。

那么就让我们利用,new Image()来搞事情

二、预加载和预加载动画实现

1、批量设置图片路径

平常我们在接触img元素的时候,都知道书写img标签的时候,必然少不了添加src属性,不然图片加载不出来。所以我们第一步就是批量设置这些需要预加载的图片路径地址,这样onload才能发挥其作用。

这里的图片太多了,一张一张的手写,未免太麻烦了。为了节省时间,这里我拿出一年多以前刚刚学Node的时候写的一个js脚本,来批量获取图片名称生成数组对象列表。

node生成的数组.png

PS:这里就不挂载nodefs脚本代码,文末我将会这个小demo地址附上(包括nodefs.js),感兴趣的小伙伴可以点击访问。

2、预加载图片效果测试

因为我此前是用的webpack工具构建的项目,支持模块引入imglist.js. 这里我为了demo演示,因此我们就直接将这个数组对象复制粘贴到演示HTML当中。

<body>
    <h1 class="loading"></h1>
</body>
</html>
<script>
    let imglist = [{name: 'AKM', url: 'AKM.png'},{name: 'AUG', url: 'AUG.png'},{name: 'AWM', url: 'AWM.png'},{name: 'crossbow', url: 'crossbow.png'},{name: 'Crowbar', url: 'Crowbar.png'},{name: 'DP-28', url: 'DP-28.png'},{name: 'G36C', url: 'G36C.png'},{name: 'Groza', url: 'Groza.png'},{name: 'Kar98k', url: 'Kar98k.png'},{name: 'M16A4', url: 'M16A4.png'},{name: 'M24', url: 'M24.png'},{name: 'M249', url: 'M249.png'},{name: 'M416', url: 'M416.png'},{name: 'M762', url: 'M762.png'},{name: 'Machete', url: 'Machete.png'},{name: 'Micro-UZI', url: 'Micro-UZI.png'},{name: 'Mini14', url: 'Mini14.png'},{name: 'Mk14', url: 'Mk14.png'},{name: 'MK47', url: 'MK47.png'},{name: 'P18C', url: 'P18C.png'},{name: 'p1911', url: 'p1911.png'},{name: 'P92', url: 'P92.png'},{name: 'Pan', url: 'Pan.png'},{name: 'QBU', url: 'QBU.png'},{name: 'QBZ', url: 'QBZ.png'},{name: 'R1895', url: 'R1895.png'},{name: 'R45', url: 'R45.png'},{name: 'S12K', url: 'S12K.png'},{name: 'S1897', url: 'S1897.png'},{name: 'S686', url: 'S686.png'},{name: 'Sawed-off', url: 'Sawed-off.png'},{name: 'SCAR-L', url: 'SCAR-L.png'},{name: 'Scorpion', url: 'Scorpion.png'},{name: 'Sickle', url: 'Sickle.png'},{name: 'Signal', url: 'Signal.png'},{name: 'SKS', url: 'SKS.png'},{name: 'SLR', url: 'SLR.png'},{name: 'Thomson', url: 'Thomson.png'},{name: 'UMP9', url: 'UMP9.png'},{name: 'Vector', url: 'Vector.png'},{name: 'VSS', url: 'VSS.png'},{name: 'win94', url: 'win94.png'}];
    let length = imglist.length;
    let images = new Array(); // 定义一个数组容器,用来存储预加载完成的图片
    let loadEl = document.querySelector('.loading');
    function preload () {
        let count = 0; // 计算器,计算加载了多少图片
        for (let i = 0; i < length; i++) {
            images[i] = new Image();
            images[i].src = `./imgs/${imglist[i].url}`; 
            // 谷歌浏览器高版本支持大部分ES6,所以这里就不用字符串拼接了。
            images[i].onload = function () {
                count++;
                if (count === length) {
                    loadEl.innerHTML = '加载完成';
                } else {
                    loadEl.innerHTML = '正在加载中';
                }
            }
        }
    }
    preload();
</script>

打开页面重新刷新一下,在控制台NetWork可以将图片全部加载出来。emmm,但是由于本地加载速度太快了,一下子就加载完成。通过下面截图可以看到,加载时间不到1s就加载,并不能很好看的预加载过程。

加载太快.png

3、预加载图片真实环境模拟

所以为了小伙伴们能够更加直观的看到预加载的过程,这里我们决定进行真实环境模拟:

①这里我利用vscode自带的插件,生成一个本地服务器。

vscode-live.png

②然后在切换到浏览器控制台下NetWork,将网速调整为Fast3G

Fast3G.png

③ 然后将之前加载中的代码修改,成百分比显示。

// loadEl.innerHTML = '正在加载中';
loadEl.innerHTML = `正在加载中${Math.round(count / length * 100)}%`;

最终效果如下:

GIF-1552205242262.gif

三、小结

好了!以上就是鄙人对于前端图片预加载一点简单理解与复习了,主要回顾一些image()基本属性点。

当然,前端图片预加载方法也并不止这么一种,方法还是有好几种。所以后续使用何种方法就各位小伙伴自己了。这里有一篇大佬翻译的文章就提到三种前端预加载的方法,希望可以给大家一个参考。

这篇文章中的第二个方法,就是本文采用的方法。所以希望各位大佬待会点进看完之后,不要出来打我。毕竟我不是大佬代码水平,我只是一个快乐前端段子手。

传送门地址:译:利用CSS、JavaScript及Ajax实现图片预加载的三大方法

我绝不道歉.png

考虑新年第一篇文章,吹水过多不在状态,所以良(很)心(皮)的我,决定锦上添花额外写一个快乐loading动画作为给我大哥赔罪。

快乐loading小动画

CSS3预加载动画.gif

这里就是百分比数字,分割成两位,然后通过数字的不同,改变图片background-position属性,来完成loading预加载动画。

 images[i].onload = function () {
    count++;
    if (count === length) {
        loadStart.style.display = 'none';
            loadEnd.style.display = 'block';
            loadEnd.onclick = function () {
                alert('恭喜学习图片预加载!');
            }
     } else {
       // loadEl.innerHTML = '正在加载中';
       // loadEl.innerHTML = `正在加载中${Math.round(count / length * 100)}%`;
       let text = Math.round(count / length * 100);
       let text1 = parseInt(text / 10);
       let text2 = parseInt(text % 10);
       console.log(text1, text2);
       num1.style.backgroundPositionX = `${-47 + text1 * -60}px`
       num2.style.backgroundPositionX = `${-47 + text2 * -60}px`
      }
  }

所以对完整blogDemo代码感兴趣的,可以从本人github上阅览。

源码demo传送门地址

原创文章,文笔有限,才疏学浅,文中若有不正之处,再次再次再次欢迎各位啪啪的打脸赐教。(有句话说的好,重要的词得说三遍。)

我是车大棒!我为我自己带眼了!

皮皮虾我们走.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • 课程前言: 慕课网 --图片预加载 图片预加载的特点: ( 1、网站的Loading页 2、局部图片的加载--表情...
    一树青枫阅读 3,660评论 0 2
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,093评论 4 62
  • 常见试题 行内元素:会在水平方向排列,不能包含块级元素,设置width无效,height无效(可以设置line-h...
    他大舅啊阅读 2,439评论 1 5
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,474评论 1 45
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,096评论 1 32