Best way to preload images with Angular.js

2019-01-16 07:01发布

Angular's ng-src keeps previous model until it preloads image internally. I am using different image for the banner on each page, when I switch routes, i change main view, leaving header view as it is, just changing bannerUrl model when I have it.

This is resulting in seeing previous banner image while new one is loading.

I was surprised that there's no directive for it yet, but I wanted to make a discussion before trying to build one.

What I want to do I think is have banner model on custom attribute. like:

<img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}">

Then $scope.watch for bannerUrl change, and as soon as it changes, replace ng-src with loader spinner first, and then create temproary img dom element, preload image from preload-src and then assing it to preloadUrl.

Need to think how to handle multiple images too for galleries for example.

Does anyone have any input on it? or maybe someone can point me to existing code?

I've seen existing code on github that uses background-image - but that doesn't work for me as I need dynamic height/width as my app is responsive, and I cannot do it with background-image.

Thank you

9条回答
我只想做你的唯一
2楼-- · 2019-01-16 07:32

If anyone is interested this is my final solution: I use twitter bootstrap. So added class of "fade" to all images and just toggling class "in" with directive to fade in and out when image is loaded

angular.module('myApp').directive('imgPreload', ['$rootScope', function($rootScope) {
    return {
      restrict: 'A',
      scope: {
        ngSrc: '@'
      },
      link: function(scope, element, attrs) {
        element.on('load', function() {
          element.addClass('in');
        }).on('error', function() {
          //
        });

        scope.$watch('ngSrc', function(newVal) {
          element.removeClass('in');
        });
      }
    };
}]);

<img img-preload class="fade" ng-src="{{imgSrc}}">

Working example: http://ishq.org

查看更多
甜甜的少女心
3楼-- · 2019-01-16 07:32

A simple solution I've found is to change the url to '//:0' before assigning it's new value

$scope.bannerUrl = 'initial value'; 

// When we want to change it
$scope.bannerUrl = '//:0';  // remove the previous img so it's not visible while the new one loads
$scope.bannerUrl = scope.preloadedUrl
查看更多
姐就是有狂的资本
4楼-- · 2019-01-16 07:35

Instead of using

element.on('load', function() {});

use imagesLoaded plugin. It will speed up dramatically your images.

So the final code would be:

link: function(scope, element) {
  imagesLoaded(element, function() {

  });
  scope.$watch('ngSrc', function() {

  });
}
查看更多
登录 后发表回答