优势- 性能收益:浏览器加载图片、decode、渲染都需要耗费资源,懒加载能节约性能消耗,缩短onload事件时间。
- 节约带宽:这个不需要解释。
通常,我们在html中展示图片,会有两种方式: - img 标签
- css background-image
img的懒加载实现img有两种方式实现懒加载: - 事件监听(scroll、resize、orientationChange)
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>event</title>
- <style>
- img {
- background: #F1F1FA;
- width: 400px;
- height: 300px;
- display: block;
- margin: 10px auto;
- border: 0;
- }
- </style>
- </head>
- <body>
- <img src="https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300" />
- <img src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
- <img src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" /> -->
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image5.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image6.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image7.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image8.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image9.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-400,h-300" />
- <script>
- document.addEventListener("DOMContentLoaded", function() {
- var lazyloadImages = document.querySelectorAll("img.lazy");
- var lazyloadThrottleTimeout;
-
- function lazyload () {
- if(lazyloadThrottleTimeout) {
- clearTimeout(lazyloadThrottleTimeout);
- }
-
- lazyloadThrottleTimeout = setTimeout(function() {
- var scrollTop = window.pageYOffset;
- lazyloadImages.forEach(function(img) {
- if(img.offsetTop < (window.innerHeight + scrollTop)) {
- img.src = img.dataset.src;
- img.classList.remove('lazy');
- }
- });
- if(lazyloadImages.length == 0) {
- document.removeEventListener("scroll", lazyload);
- window.removeEventListener("resize", lazyload);
- window.removeEventListener("orientationChange", lazyload);
- }
- }, 20);
- }
-
- document.addEventListener("scroll", lazyload);
- window.addEventListener("resize", lazyload);
- window.addEventListener("orientationChange", lazyload);
- });
- </script>
- </body>
- </html>
复制代码
- Intersection Observer(兼容性问题)
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>observer</title>
- <style>
- img {
- background: #F1F1FA;
- width: 400px;
- height: 300px;
- display: block;
- margin: 10px auto;
- border: 0;
- }
- </style>
- </head>
- <body>
- <img src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
- <img src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" /> -->
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image5.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image6.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image7.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image8.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image9.jpeg?tr=w-400,h-300" />
- <img class="lazy" data-src="https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-400,h-300" />
- <script>
- document.addEventListener("DOMContentLoaded", function() {
- var lazyloadImages = document.querySelectorAll(".lazy");
- var imageObserver = new IntersectionObserver(function(entries, observer) {
- entries.forEach(function(entry) {
- if (entry.isIntersecting) {
- var image = entry.target;
- image.src = image.dataset.src;
- image.classList.remove("lazy");
- imageObserver.unobserve(image);
- }
- });
- });
- lazyloadImages.forEach(function(image) {
- imageObserver.observe(image);
- });
- });
- </script>
- </body>
- </html>
复制代码
background-image的实现background-image的实现跟img的原理基本是一样的,区别是在对class的处理上:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>background</title>
- <style>
- body {
- margin: 0;
- }
- .bg {
- height: 200px;
- }
- #bg-image.lazy {
- background-image: none;
- background-color: #F1F1FA;
- }
- #bg-image {
- background-image: url("https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300");
- background-size: 100%;
- }
- </style>
- </head>
- <body>
- <div id="bg-image" class="bg lazy"></div>
- <div id="bg-image" class="bg lazy"></div>
- <div id="bg-image" class="bg lazy"></div>
- <div id="bg-image" class="bg lazy"></div>
- <div id="bg-image" class="bg lazy"></div>
- <div id="bg-image" class="bg lazy"></div>
- <div id="bg-image" class="bg lazy"></div>
- <div id="bg-image" class="bg lazy"></div>
- <script>
- document.addEventListener("DOMContentLoaded", function() {
- var lazyloadImages = document.querySelectorAll(".lazy");
- var imageObserver = new IntersectionObserver(function(entries, observer) {
- entries.forEach(function(entry) {
- if (entry.isIntersecting) {
- var image = entry.target;
- image.classList.remove("lazy");
- imageObserver.unobserve(image);
- }
- });
- });
- lazyloadImages.forEach(function(image) {
- imageObserver.observe(image);
- });
- });
- </script>
- </body>
- </html>
复制代码
渐进式懒加载渐进式懒加载,指的是存在降级处理,通常html形式如下:
- <a href="full.jpg" class="progressive replace">
- <img src="tiny.jpg" class="preview" alt="image" />
- </a>
复制代码
这样的代码会有2个好处: - 如果js执行失败,可以点击预览
- 大小与实际图一致的占位data URI,避免reflow
最终的代码如下:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>progressive</title>
- <style>
- a.progressive {
- position: relative;
- display: block;
- overflow: hidden;
- outline: none;
- }
- a.progressive:not(.replace) {
- cursor: default;
- }
- a.progressive img {
- display: block;
- width: 100%;
- max-width: none;
- height: auto;
- border: 0 none;
- }
- a.progressive img.preview {
- filter: blur(2vw);
- transform: scale(1.05);
- }
- a.progressive img.reveal {
- position: absolute;
- left: 0;
- top: 0;
- will-change: transform, opacity;
- animation: reveal 1s ease-out;
- }
- @keyframes reveal {
- 0% {transform: scale(1.05); opacity: 0;}
- 100% {transform: scale(1); opacity: 1;}
- }
- </style>
- </head>
- <body>
- <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg" data-srcset="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg 800w, https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5big.jpg 1600w" class="progressive replace">
- <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gNzAK/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgABQAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A5yC3e2S3gM7OEQHdgA57VTuLAPqUoaUk7yM7R2BPSiivS5VN8stjmk2ldGVM3lyshG7bxk0UUV4skk2jdN2P/9k=" class="preview" alt="palm trees" />
- </a>
- <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature2.jpg" class="progressive replace">
- <img src="http://lorempixel.com/20/15/nature/2/" class="preview" alt="sunset" />
- </a>
- <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature3.jpg" class="progressive replace">
- <img src="http://lorempixel.com/20/15/nature/3/" class="preview" alt="tide" />
- </a>
- <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg" data-srcset="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg 800w, https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5big.jpg 1600w" class="progressive replace">
- <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gNzAK/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgABQAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A5yC3e2S3gM7OEQHdgA57VTuLAPqUoaUk7yM7R2BPSiivS5VN8stjmk2ldGVM3lyshG7bxk0UUV4skk2jdN2P/9k=" class="preview" alt="palm trees" />
- </a>
- <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature2.jpg" class="progressive replace">
- <img src="http://lorempixel.com/20/15/nature/2/" class="preview" alt="sunset" />
- </a>
- <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature3.jpg" class="progressive replace">
- <img src="http://lorempixel.com/20/15/nature/3/" class="preview" alt="tide" />
- </a>
- <script>
- window.addEventListener('load', function() {
- var pItem = document.getElementsByClassName('progressive replace'), timer;
- window.addEventListener('scroll', scroller, false);
- window.addEventListener('resize', scroller, false);
- inView();
- function scroller(e) {
- timer = timer || setTimeout(function() {
- timer = null;
- requestAnimationFrame(inView);
- }, 300);
- }
- function inView() {
- var scrollTop = window.pageYOffset;
- var innerHeight = window.innerHeight;
- var p = 0;
- while (p < pItem.length) {
- var offsetTop = pItem[p].offsetTop;
- if (offsetTop < (scrollTop + innerHeight)) {
- loadFullImage(pItem[p]);
- pItem[p].classList.remove('replace');
- }
- else p++;
- }
- }
- function loadFullImage(item) {
- var img = new Image();
- if (item.dataset) {
- img.srcset = item.dataset.srcset || '';
- img.sizes = item.dataset.sizes || '';
- }
- img.src = item.href;
- img.className = 'reveal';
- if (img.complete) addImg();
- else img.onload = addImg;
- function addImg() {
- item.addEventListener('click', function(e) { e.preventDefault(); }, false);
- item.appendChild(img).addEventListener('animationend', function(e) {
- var pImg = item.querySelector('img.preview');
- if (pImg) {
- e.target.alt = pImg.alt || '';
- item.removeChild(pImg);
- e.target.classList.remove('reveal');
- }
- });
- }
- }
- }, false);
- </script>
- </body>
- </html>
复制代码
|