Skip to content

Instantly share code, notes, and snippets.

@michalkvasnicak
Last active December 2, 2019 23:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michalkvasnicak/23a6867403f55ab46452 to your computer and use it in GitHub Desktop.
Save michalkvasnicak/23a6867403f55ab46452 to your computer and use it in GitHub Desktop.
Better image lazy loading in AngularJS
angular.module('Demo', []).service(
'scrollAndResizeListener', function($window, $document, $timeout) {
var id = 0,
listeners = {},
scrollTimeoutId,
resizeTimeoutId;
function invokeListeners() {
var clientHeight = $document[0].documentElement.clientHeight,
clientWidth = $document[0].documentElement.clientWidth;
for (var key in listeners) {
if (listeners.hasOwnProperty(key)) {
listeners[key](clientHeight, clientWidth); // call listener with given arguments
}
}
}
$window.addEventListener('scroll', function() {
// cancel previous timeout (simulates stop event)
$timeout.cancel(scrollTimeoutId);
// wait for 200ms and then invoke listeners (simulates stop event)
scrollTimeoutId = $timeout(invokeListeners, 200);
});
$window.addEventListener('resize', function() {
$timeout.cancel(resizeTimeoutId);
resizeTimeoutId = $timeout(invokeListeners, 200);
});
return {
bindListener: function(listener) {
var index = ++id;
listeners[id] = listener;
return function() {
delete listeners[index];
}
}
};
}
);
angular.module('Demo').directive(
'imageLazySrc', function ($document, scrollAndResizeListener) {
return {
restrict: 'A',
link: function ($scope, $element, $attributes) {
var listenerRemover;
function isInView(clientHeight, clientWidth) {
// get element position
var imageRect = $element[0].getBoundingClientRect();
if (
(imageRect.top >= 0 && imageRect.bottom <= clientHeight)
&&
(imageRect.left >= 0 && imageRect.right <= clientWidth)
) {
$element[0].src = $attributes.imageLazySrc; // set src attribute on element (it will load image)
// unbind event listeners when image src has been set
listenerRemover();
}
}
// bind listener
listenerRemover = scrollAndResizeListener.bindListener(isInView);
// unbind event listeners if element was destroyed
// it happens when you change view, etc
$element.on('$destroy', function () {
listenerRemover();
});
// explicitly call scroll listener (because, some images are in viewport already and we haven't scrolled yet)
isInView(
$document[0].documentElement.clientHeight,
$document[0].documentElement.clientWidth
);
}
};
}
);
@ijamaatlou
Copy link

ijamaatlou commented Nov 27, 2019

Thank you Michal for your code,
I tried it but it doesn't work on element that already exist on page not after scroll.
Am i wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment