图片懒加载 echo.js
1 (function (root, factory) { 2 if (typeof define === 'function' && define.amd) { 3 define(function() { 4 return factory(root); 5 }); 6 } else if (typeof exports === 'object') { 7 module.exports = factory; 8 } else { 9 root.echo = factory(root); 10 } 11 })(this, function (root) { 12 13 'use strict'; 14 15 var echo = {}; 16 17 var callback = function () {}; 18 19 var offset, poll, delay, useDebounce, unload; 20 21 var isHidden = function (element) { 22 return (element.offsetParent === null); 23 }; 24 25 var inView = function (element, view) { 26 if (isHidden(element)) { 27 return false; 28 } 29 30 var box = element.getBoundingClientRect(); 31 return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b); 32 }; 33 34 var debounceOrThrottle = function () { 35 if(!useDebounce && !!poll) { 36 return; 37 } 38 clearTimeout(poll); 39 poll = setTimeout(function(){ 40 echo.render(); 41 poll = null; 42 }, delay); 43 }; 44 45 echo.init = function (opts) { 46 opts = opts || {}; 47 var offsetAll = opts.offset || 0; 48 var offsetVertical = opts.offsetVertical || offsetAll; 49 var offsetHorizontal = opts.offsetHorizontal || offsetAll; 50 var optionToInt = function (opt, fallback) { 51 return parseInt(opt || fallback, 10); 52 }; 53 offset = { 54 t: optionToInt(opts.offsetTop, offsetVertical), 55 b: optionToInt(opts.offsetBottom, offsetVertical), 56 l: optionToInt(opts.offsetLeft, offsetHorizontal), 57 r: optionToInt(opts.offsetRight, offsetHorizontal) 58 }; 59 delay = optionToInt(opts.throttle, 250); 60 useDebounce = opts.debounce !== false; 61 unload = !!opts.unload; 62 callback = opts.callback || callback; 63 echo.render(); 64 if (document.addEventListener) { 65 root.addEventListener('scroll', debounceOrThrottle, false); 66 root.addEventListener('load', debounceOrThrottle, false); 67 } else { 68 root.attachEvent('onscroll', debounceOrThrottle); 69 root.attachEvent('onload', debounceOrThrottle); 70 } 71 }; 72 73 echo.render = function () { 74 var nodes = document.querySelectorAll('img[data-echo], [data-echo-background]'); 75 var length = nodes.length; 76 var src, elem; 77 var view = { 78 l: 0 - offset.l, 79 t: 0 - offset.t, 80 b: (root.innerHeight || document.documentElement.clientHeight) + offset.b, 81 r: (root.innerWidth || document.documentElement.clientWidth) + offset.r 82 }; 83 for (var i = 0; i < length; i++) { 84 elem = nodes[i]; 85 if (inView(elem, view)) { 86 87 if (unload) { 88 elem.setAttribute('data-echo-placeholder', elem.src); 89 } 90 91 if (elem.getAttribute('data-echo-background') !== null) { 92 elem.style.backgroundImage = "url(" + elem.getAttribute('data-echo-background') + ")"; 93 } 94 else { 95 elem.src = elem.getAttribute('data-echo'); 96 } 97 98 if (!unload) { 99 elem.removeAttribute('data-echo'); 100 elem.removeAttribute('data-echo-background'); 101 } 102 103 callback(elem, 'load'); 104 } 105 else if (unload && !!(src = elem.getAttribute('data-echo-placeholder'))) { 106 107 if (elem.getAttribute('data-echo-background') !== null) { 108 elem.style.backgroundImage = "url(" + src + ")"; 109 } 110 else { 111 elem.src = src; 112 } 113 114 elem.removeAttribute('data-echo-placeholder'); 115 callback(elem, 'unload'); 116 } 117 } 118 if (!length) { 119 echo.detach(); 120 } 121 }; 122 123 echo.detach = function () { 124 if (document.removeEventListener) { 125 root.removeEventListener('scroll', debounceOrThrottle); 126 } else { 127 root.detachEvent('onscroll', debounceOrThrottle); 128 } 129 clearTimeout(poll); 130 }; 131 132 return echo; 133 134 });
如何使用
1、引入文件
- <script src="js/echo.min.js"></script>
2、HTML结构
- <img src="img/blank.gif" alt="Photo" data-echo="img/photo.jpg" />
blank.gif 是一个 1 x 1 的图片,用做默认图片,data-echo 的属性值是图片的真实地址。你可以给图片设置宽度和高度,或者在 CSS 中设置,否则似乎很底部很底部的图片才会延迟加载。
3、JavaScript
1 echo.init({ 2 offset: 100, 3 throttle: 250, 4 unload: false, 5 callback: function (element, op) { 6 console.log('loaded ok.'); 7 } 8 });
4、常用参数及方法说明
参数 | 描述 | 默认值 |
offset | 离可视区域多少像素的图片可以被加载 | 0 |
throttle | 图片延迟多少毫秒加载 | 250 |
debounce | 防抖动 | true |
unload | 告诉echo是加载还是卸载视图中的图片,当图片离开视图区域时触发 | false |
callback | 回调函数,用来检测图片是否加载 | function() |
最后echo.js还提供了一个.render()方法,用法如下:
echo.render();
应用场景:当你的页面没有发生滚动,而你想加载即将要显示的图片,如图片轮播,当第一张图片显示完,接着滑动展示第二张图片,这个时候使用echo.render()
提前加载第二张图片,就不会出现图片加载卡顿白屏等现象。