Skip to content

Commit

Permalink
feat(lazy-images): lazy load images
Browse files Browse the repository at this point in the history
  • Loading branch information
berndartmueller committed Sep 2, 2020
1 parent 7ad358c commit 9a154da
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 12 deletions.
8 changes: 6 additions & 2 deletions entry/entry-complete.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { Controls } from './../src/components/controls';
import { Lazy } from './../src/components/lazy';
import { Controls } from './../src/components/controls/controls';
import { Lazy } from './../src/components/lazy/lazy';
import { LazyLoadImage } from './../src/components/lazyload-image/lazyload-image';
import { Virchual as VirchualCore, VirchualSettings } from './../src/virchual';

// @TODO settings with combined settings from components

export default class Virchual extends VirchualCore {
constructor(container: HTMLElement, settings: VirchualSettings = {}) {
super(container, settings);

this.register(Controls, { isEnabled: true });
this.register(Lazy, { threshold: 300 });
this.register(LazyLoadImage, { lazyload: false });
}
}
5 changes: 3 additions & 2 deletions entry/entry-modular.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Virchual } from './../src/virchual';

export { Controls } from './../src/components/controls';
export { Lazy } from './../src/components/lazy';
export { Controls } from './../src/components/controls/controls';
export { Lazy } from './../src/components/lazy/lazy';
export { LazyLoadImage } from './../src/components/lazyload-image/lazyload-image';

export default {
Virchual,
Expand Down
8 changes: 5 additions & 3 deletions examples/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { LazyLoadImage } from './../../src/components/lazyload-image/lazyload-image';
import Virchual from '@virchual/index';
import { Controls } from '@virchual/components/controls/controls';

Expand All @@ -24,15 +25,15 @@ import './../../src/css/styles.css';
const imageId = unsplashImageIds[i - 1];

slides.push(`
<picture>
<picture class="virchual__lazy-img">
<source
type="image/jpeg"
srcSet="
data-srcSet="
https://source.unsplash.com/${imageId}/400x265,
https://source.unsplash.com/${imageId}/800x530 2x
"
/>
<img src="https://source.unsplash.com/${imageId}/400x265" itemProp="image" />
<img data-src="https://source.unsplash.com/${imageId}/400x265" />
</picture>
`);
}
Expand All @@ -42,6 +43,7 @@ import './../../src/css/styles.css';
});

instance.register(Controls, { isEnabled: true });
instance.register(LazyLoadImage);

instance.mount();
});
1 change: 1 addition & 0 deletions src/components/lazyload-image/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lazyload-image';
97 changes: 97 additions & 0 deletions src/components/lazyload-image/lazyload-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { ComponentDependencies } from './../component';

export type LazyLoadImageSettings = {
/**
* Enables lazyloading imagest that are currently not visible, thus saving bandwidth.
*/
lazyload?: boolean;

/**
* The CSS selector for lazyloaded images. Default 'virchual__lazy-img'
*/
lazyloadSelector?: string;

/**
* How many images should get eagerly loaded on both sides of current slide.
*/
loadEager?: number;
};

export class LazyLoadImage {
private lazyload: boolean;
private lazyloadSelector: string;
private loadEager: number;

constructor(private imports: ComponentDependencies, settings: LazyLoadImageSettings) {
const { lazyload, lazyloadSelector, loadEager } = {
lazyload: true,
lazyloadSelector: '.virchual__lazy-img',
loadEager: 1,
...settings,
};

this.lazyload = lazyload;
this.lazyloadSelector = lazyloadSelector;
this.loadEager = loadEager;

imports.eventBus.on('mounted', () => {
this.lazyLoad();
});

imports.eventBus.on('move', () => {
this.lazyLoad();
});
}

private lazyLoad(): void {
const images = this.getImages(this.imports.virchual.currentIndex, this.imports.virchual.currentIndex + 1);

images.forEach(image => {
this.loadImage(image);
});
}

private loadImage(image: HTMLImageElement) {
// @todo handle picture and img element slightly different

[].forEach.call(image.getElementsByTagName('source'), (source: HTMLSourceElement) => {
const dataSrc = source.dataset.srcset;

if (dataSrc) {
source.setAttribute('srcset', dataSrc);

source.removeAttribute('data-srcset');
}
});

image.classList.add('loading');
}

private getImages(start: number, end: number) {
if (start - this.loadEager >= 0) {
start = start - this.loadEager;
}

if (this.imports.virchual.slides.length > end + this.loadEager) {
end = end + this.loadEager;
}

const images = [];

while (start <= end) {
const slide = this.imports.virchual.slides[start];

start++;

if (!slide.isMounted) {
continue;
}

[].forEach.call(slide.ref.querySelectorAll(this.lazyloadSelector), (img: HTMLElement) => {
images.push(img);
});
}

return images;
}
}
2 changes: 1 addition & 1 deletion src/slide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { VirchualSettings } from './virchual';
* Virtual slide component.
*/
export class Slide {
ref: HTMLElement;
isMounted = false;
isActive = false;
position: number;

private hasChanged = false;
private html: string;
private ref: HTMLElement;
private transitionEndCallback: identity;

constructor(html: string | HTMLElement, private frame: HTMLElement, private settings: VirchualSettings) {
Expand Down
8 changes: 5 additions & 3 deletions src/virchual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export type VirchualSettings = {
export class Virchual {
frame: HTMLElement;
currentIndex = 0;
slides: Slide[] = [];

private slides: Slide[] = [];
private eventBus: Event;
private isBusy = false;
private pagination: Pagination;
Expand Down Expand Up @@ -95,13 +95,13 @@ export class Virchual {
mount() {
console.debug('[Mount] Virchual');

this.eventBus.emit('mounted');

this.mountAndUnmountSlides();

this.bindEvents();

new Drag(this.frame, { event: this.eventBus }).mount();

this.eventBus.emit('mounted');
}

/**
Expand Down Expand Up @@ -191,6 +191,8 @@ export class Virchual {
const move = control === 'prev' ? this.pagination.prev.bind(this.pagination) : this.pagination.next.bind(this.pagination);

move();

this.eventBus.emit('move', { index: this.currentIndex, control });
}

private hydrate(): Slide[] {
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"@virchual/*": ["src/*"]
}
},
"include": ["./src/**/*", "./examples/src/**/*"],
"include": ["./src/**/*", "./examples/src/**/*", "./entry/*"],
"exclude": ["node_modules"]
}

0 comments on commit 9a154da

Please sign in to comment.