web-dev-qa-db-ja.com

Angular.jsで画像をプリロードする最良の方法

Angularのng-srcは、画像を内部的にプリロードするまで前のモデルを保持します。私は各ページのバナーに異なる画像を使用しています。ルートを切り替えるとき、メインビューを変更し、ヘッダービューをそのままにして、持っているときにbannerUrlモデルを変更します。

これにより、新しいバナーの読み込み中に以前のバナー画像が表示されます。

まだ指令がないのには驚いたが、構築する前に議論をしたかった。

私がやりたいことは、カスタム属性にバナーモデルがあることです。のような:

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

次に、bannerUrlの変更用の$ scope.watchを変更し、変更したらすぐにng-srcをローダースピナーに置き換え、次に一時的なimg dom要素を作成し、preload-srcからイメージをプリロードしてから、preloadUrlにアサートします。

たとえば、ギャラリーでも複数の画像を処理する方法を考える必要があります。

誰もが何か入力をしていますか?または誰かが私に既存のコードを指すことができますか?

Background-imageを使用するgithubで既存のコードを見てきましたが、アプリが応答するため動的な高さ/幅が必要であり、background-imageでそれを行うことができないため、私には機能しません。

ありがとうございました

26
Yuri

ディレクティブに2つのURLがあると、タッチが複雑になりすぎます。私がより良いと思うのは、次のように機能するディレクティブを書くことです:

<img ng-src="{{bannerUrl}}" spinner-on-load />

また、ディレクティブはng-srcを監視し、(たとえば)画像が読み込まれるまでスピナーでvisibility:falseを設定できます。のようなもの:

scope: {
  ngSrc: '='
},
link: function(scope, element) {
  element.on('load', function() {
    // Set visibility: true + remove spinner overlay
  });
  scope.$watch('ngSrc', function() {
    // Set visibility: false + inject temporary spinner overlay
  });
}

このように、要素はng-src属性を持つ標準のimgと非常によく似た振る舞いをします。

http://jsfiddle.net/2CsfZ/47/

48
Michal Charemza

誰かが興味を持っているなら、これが私の最終的な解決策です。Twitterブートストラップを使用します。そのため、すべての画像に「フェード」クラスを追加し、画像が読み込まれたときにフェードインおよびフェードアウトするディレクティブでクラス「in」を切り替えるだけです

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}}">

作業例: http://ishq.org

24
Yuri

必要に応じて、ディレクティブの属性として画像の失敗と画像ローダーを渡すことができます。

myApp.directive("mySrc", function() {
    return {
      link: function(scope, element, attrs) {
        var img, loadImage;
        var IMAGE_LOAD="123.jpg";
        var IMAGE_FAIL="123.jpg";
        img = null;

        loadImage = function() {

          element[0].src = IMAGE_LOAD;

          img  = new Image();
          img.src = attrs.mySrc;

          img.onload = function() {
            element[0].src = attrs.mySrc;
          };
          img.onerror=function ()
          {
              element[0].src = IMAGE_FAIL;
          }
        };

        loadImage();


      }
    };
  });
3
yonia

ディレクティブが実際にスピナーを作成し、自動的に削除するため、これはおそらく最もエレガントなソリューションだと思います:

app.directive('spinnerLoad', [function spinnerLoad() {
    return {
        restrict: 'A',
        link: function spinnerLoadLink(scope, elem, attrs) {
            scope.$watch('ngSrc', function watchNgSrc() {
                elem.hide();
                elem.after('<i class="fa fa-spinner fa-lg fa-spin"></i>');  // add spinner
            });
            elem.on('load', function onLoad() {
                elem.show();
                elem.next('i.fa-spinner').remove(); // remove spinner
            });
        }
    };
}]);

Htmlは次のとおりです。

<img ng-src='{{imgUrl}}' spinner-load />

注:ここで説明されているように動作させるには、font-awesomeを使用する必要があります

2
Jeremy Moritz

代わりに

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

imagesLoaded プラグインを使用します。画像を劇的に高速化します。

したがって、最終的なコードは次のようになります。

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

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

  });
}
1
borN_free

共有するだけ^^

 //css
.media-box{
                position: relative;
                width:220px;
                height: 220px;
                overflow: hidden;
            }
            .media-box div{
                position: absolute;
                left: 0;
                top: 0;
            }
            .spinner{
                position: absolute;
                left: 0;
                top: 0;
                background: #CCC url(./spinner.gif) no-repeat center center;
                display: block;
                width:220px;
                height: 220px;
            }
            .feed img.spinner-show{
                visibility: visible;
            }
            .feed img.spinner-hide{
                visibility: hidden;
            }

//html
<div class="media-box">
  <div>
    <img data-ng-src="{{item.media}}" alt="" title="" data-spinner-on-load>
  </div>
</div>

//js
.directive('spinnerOnLoad', function() {
            return {
                restrict: 'A',
                link: function(scope,element){
                    element.on('load', function() {
                        element.removeClass('spinner-hide');
                        element.addClass('spinner-show');
                        element.parent().find('span').remove();
                    });
                    scope.$watch('ngSrc', function() {
                        element.addClass('spinner-hide');
                        element.parent().append('<span class="spinner"></span>');
                    });      
                }
            }
        });
1
Whisher

Img-srcが変更されたときにスピナーを表示するこのディレクティブがあります:

<img-with-loading
      img-src="{{src}}"
      spinner-class="{{spinnerClass}}"
/>

ここにコード: http://jsfiddle.net/ffabreti/yw74upyr/

0

ルート変更時に image-preloader factoryを使用してイメージをプリロードし、解決することができます:

// call REST
                    return getContent.get().$promise.then(function(response) {

                                //return response;

                                // preload images from response
                                var imageLocations = [
                                  // put image(s) from response to array
                                  response.PostImage.big[0],
                                ];

                                // check do we have (all) image(s) in array
                                console.log(imageLocations);

                                // return when all images are preloaded
                                return preloader.preloadImages( imageLocations )
                                .then(function() {

                                    //if it was success 
                                    return response;
                                },
                                function() {

                                        //if it failed 
                                    return response;
                                });

                            });

ここでチュートリアルを完了してください: https://www.coditty.com/code/angular-preload-images-on-route-change-by-using-resolve

0
Igor Simic