Mika Vatanen
Mika Vatanen

Reputation: 4027

How to show a placeholder-image before the real image is downloaded?

The idea is to show a low-res version of an image before the real high-resolution image has been downloaded, ideally using an img tag.

<img lowres="http://localhost/low-res-image.jpg" ng-src="http://localhost/low-res-image.jpg">

Low-res image would be visible first, and be replaced with high-res image after it has been downloaded. How can this be done? Is it possible to edit img.src attribute, or should something else (e.g. a wrapper div with background, or another temporary div) be created?

Upvotes: 10

Views: 14351

Answers (6)

OneGhana
OneGhana

Reputation: 117

I found this simple solution

<img ng-src="{{::val.image}}"  width="400" height="300" alt="" onerror="this.src='img/logo-sm.png'"  src="img/logo-sm.png">

Hope it helps somenone

Upvotes: 0

Kyle Pennell
Kyle Pennell

Reputation: 6097

Because ng-src is going to replace whatever is in src why not use both?

<img src="img/placeholder.jpg" ng-src="{{actualone.img}} "  height="150px " width="300px ">

Use normal src for your placeholder. It will get replaced one the image for ng-src is ready.

Upvotes: 11

codelearner
codelearner

Reputation: 458

Simple examle. try this, without using directives
HTML

<img  ng-src="{{loading.image_url}}" >

Javascript

//within controller
    $scope.loading.image_url = 'path_to_loading_image';
    var loaded_img = 'path_to_loaded_image';
    $http.get(loaded_img).then(function() {
        $scope.loading.image_url = loaded_img;
    }, function() {
        console.log('something went wrong!');
    });

Upvotes: 1

dave
dave

Reputation: 64657

You'd probably want to create a directive, I'd actually have hires as the attribute, so that by default it starts with lores.

JS:

app.directive('hires', function() {
  return {
    restrict: 'A',
    scope: { hires: '@' },
    link: function(scope, element, attrs) {
        element.one('load', function() {
            element.attr('src', scope.hires);
        });
    }
  };
});

HTML:

<img hires="http://localhost/hi-res-image.jpg" src="http://localhost/low-res-image.jpg" />

Upvotes: 23

VicJ
VicJ

Reputation: 131

The above answer is misleading and here's why. You need to unbind the load event as it will cause infinite load loop on desktop and mobile browsers if you run it in an ng-repeat directive each src replacement will cause new load event to fire and therefore replacement of image etc. The above answer caused my app to break not only performance wise but also caused crashes on mobile devices until I added the unbind.

.directive('imageloaded', function () {
return {
  restrict: 'A',
  scope:{imageloaded:'@'},
  link: function postLink(scope, element, attrs) {
    element.bind('load', function() {
        //console.log('load fired') <- just console log it and comment the unbind and you will see the 10000s of console logs.
        element.attr('src', scope.imageloaded);
        element.unbind('load');
    });
  }
};

});

Upvotes: 5

Alborz
Alborz

Reputation: 6903

You can change the src attribute of image after it is loaded. you need to bind load event to image to find out when the image is loaded.

See this page Detect image load by jQuery

You can use a directive to set the initial src attribute and bind the load event to change src to main image.

Upvotes: 0

Related Questions