Merge pull request #97 from locomotivemtl/devenini-add-lazy-loading-utils
Add lazy loading utils & implement in Scroll.js
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { module } from 'modujs';
|
||||
import { lazyLoadImage } from '../utils/image';
|
||||
import LocomotiveScroll from 'locomotive-scroll';
|
||||
|
||||
export default class extends module {
|
||||
@@ -22,16 +23,27 @@ export default class extends module {
|
||||
})
|
||||
}
|
||||
|
||||
toggleLazy(args) {
|
||||
let src = this.getData('lazy', args.obj.el)
|
||||
if (src.length) {
|
||||
if (args.obj.el.tagName === 'IMG') {
|
||||
args.obj.el.src = src
|
||||
} else {
|
||||
args.obj.el.style.backgroundImage = `url('${src}')`
|
||||
}
|
||||
this.setData('lazy', '', args.obj.el)
|
||||
}
|
||||
/**
|
||||
* Lazy load the related image.
|
||||
*
|
||||
* @see ../utils/image.js
|
||||
*
|
||||
* It is recommended to wrap your `<img>` into an element with the
|
||||
* CSS class name `.c-lazy`. The CSS class name modifier `.-lazy-loaded`
|
||||
* will be applied on both the image and the parent wrapper.
|
||||
*
|
||||
* ```html
|
||||
* <div class="c-lazy o-ratio u-4:3">
|
||||
* <img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* @param {LocomotiveScroll} args - The Locomotive Scroll instance.
|
||||
*/
|
||||
lazyLoad(args) {
|
||||
lazyLoadImage(args.obj.target, null, () => {
|
||||
//callback
|
||||
})
|
||||
}
|
||||
|
||||
destroy() {
|
||||
|
||||
87
assets/scripts/utils/image.js
Normal file
87
assets/scripts/utils/image.js
Normal file
@@ -0,0 +1,87 @@
|
||||
const LAZY_LOADED_IMAGES = []
|
||||
|
||||
export function loadImage(url, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const $img = new Image();
|
||||
|
||||
if (options.crossOrigin) {
|
||||
$img.crossOrigin = options.crossOrigin;
|
||||
}
|
||||
|
||||
const loadCallback = () => {
|
||||
resolve({
|
||||
element: $img,
|
||||
...getImageMetadata($img),
|
||||
});
|
||||
}
|
||||
|
||||
if($img.decode) {
|
||||
$img.src = url
|
||||
$img.decode().then(loadCallback).catch(e => {
|
||||
reject(e)
|
||||
})
|
||||
} else {
|
||||
$img.onload = loadCallback
|
||||
$img.onerror = (e) => {
|
||||
reject(e);
|
||||
};
|
||||
$img.src = url
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function getImageMetadata($img) {
|
||||
return {
|
||||
url: $img.src,
|
||||
width: $img.naturalWidth,
|
||||
height: $img.naturalHeight,
|
||||
ratio: $img.naturalWidth / $img.naturalHeight,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy load the given image.
|
||||
*
|
||||
* @param {HTMLImageElement} $el - The image element.
|
||||
* @param {?string} url - The URI to lazy load into $el.
|
||||
* If falsey, the value of the `data-src` attribute on $el will be used as the URI.
|
||||
* @param {?function} callback - A function to call when the image is loaded.
|
||||
*/
|
||||
export async function lazyLoadImage($el, url, callback) {
|
||||
let src = url ? url : $el.dataset.src
|
||||
|
||||
let loadedImage = LAZY_LOADED_IMAGES.find(image => image.url === src)
|
||||
|
||||
if (!loadedImage) {
|
||||
loadedImage = await loadImage(src)
|
||||
|
||||
if (!loadedImage.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
LAZY_LOADED_IMAGES.push(loadedImage)
|
||||
}
|
||||
|
||||
if($el.src === src) {
|
||||
return
|
||||
}
|
||||
|
||||
if ($el.tagName === 'IMG') {
|
||||
$el.src = loadedImage.url;
|
||||
} else {
|
||||
$el.style.backgroundImage = `url(${loadedImage.url})`;
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
let lazyParent = $el.closest('.c-lazy');
|
||||
|
||||
if(lazyParent) {
|
||||
lazyParent.classList.add('-lazy-loaded')
|
||||
lazyParent.style.backgroundImage = ''
|
||||
}
|
||||
|
||||
$el.classList.add('-lazy-loaded')
|
||||
|
||||
callback?.()
|
||||
})
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,7 +14,7 @@
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
|
||||
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
|
||||
|
||||
<link id="stylesheet" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
|
||||
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
|
||||
</head>
|
||||
<body data-module-load>
|
||||
<div data-load-container>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html class="is-loading" lang="en" data-page="home">
|
||||
<html class="is-loading" lang="en" data-page="images">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Images | Locomotive Boilerplate</title>
|
||||
@@ -14,7 +14,7 @@
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicons/favicon-16x16.png">
|
||||
<link rel="mask-icon" href="assets/images/favicons/safari-pinned-tab.svg" color="#000000">
|
||||
|
||||
<link id="stylesheet" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
|
||||
<link id="main-css" rel="stylesheet" href="assets/styles/main.css" media="print" onload="this.media='all'; this.onload=null; this.isLoaded=true">
|
||||
</head>
|
||||
<body data-module-load>
|
||||
<div data-load-container>
|
||||
@@ -57,21 +57,59 @@
|
||||
<h4 class="c-heading -h3">Using o-ratio & img</h3>
|
||||
|
||||
<div style="width: 640px; max-width: 100%;">
|
||||
<div class="o-ratio u-4:3"><img data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
|
||||
<div class="o-ratio u-4:3"><img data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
|
||||
<div class="o-ratio u-4:3"><img data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=3" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
|
||||
<div class="o-ratio u-4:3"><img data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=4" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
|
||||
<div class="o-ratio u-4:3"><img data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=5" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" /></div>
|
||||
<div class="o-ratio u-4:3">
|
||||
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=1" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
|
||||
</div>
|
||||
<div class="o-ratio u-4:3">
|
||||
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=2" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
|
||||
</div>
|
||||
<div class="o-ratio u-4:3">
|
||||
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=3" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
|
||||
</div>
|
||||
<div class="o-ratio u-4:3">
|
||||
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=4" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
|
||||
</div>
|
||||
<div class="o-ratio u-4:3">
|
||||
<img data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=5" alt="" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="c-heading -h3">Using o-ratio & background-image</h3>
|
||||
|
||||
<div style="width: 480px; max-width: 100%;">
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=1"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=2"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=3"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=4"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="toggleLazy, Scroll, main" data-scroll-lazy="http://picsum.photos/640/480?v=5"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=1"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=2"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=3"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=4"></div>
|
||||
<div style="background-size: cover; background-position: center;" class="o-ratio u-16:9" data-scroll data-scroll-call="lazyLoad, Scroll, main" data-src="http://picsum.photos/640/480?v=5"></div>
|
||||
</div>
|
||||
|
||||
<h4 class="c-heading -h3">Using SVG viewport for ratio</h3>
|
||||
|
||||
<div style="width: 480px; max-width: 100%;">
|
||||
<img
|
||||
data-scroll
|
||||
data-scroll-call="lazyLoad, Scroll, main"
|
||||
data-src="http://picsum.photos/640/480?v=6"
|
||||
alt=""
|
||||
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
|
||||
/>
|
||||
|
||||
<img
|
||||
data-scroll
|
||||
data-scroll-call="lazyLoad, Scroll, main"
|
||||
data-src="http://picsum.photos/640/480?v=7"
|
||||
alt=""
|
||||
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
|
||||
/>
|
||||
|
||||
<img
|
||||
data-scroll
|
||||
data-scroll-call="lazyLoad, Scroll, main"
|
||||
data-src="http://picsum.photos/640/480?v=8"
|
||||
alt=""
|
||||
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'%3E%3C/svg%3E"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user