web-dev-qa-db-ja.com

ngSrcパスが404に解決される場合、デフォルトにフォールバックする方法はありますか?

作成しているアプリケーションでは、このイメージがロードされる前に、ユーザーが4つの情報を設定する必要があります。この画像はアプリケーションの中心部分であるため、画像リンクが壊れているため、全体が途切れているように見えます。 404に別の画像を置きたいのですが。

何か案は?このためのカスタムディレクティブを記述しないようにします。

特にドキュメントの最初の質問が同じものである場合、同様の質問が見つからなかったことに驚きました!

http://docs.angularjs.org/api/ng.directive:ngSrc

129
will_hardin

これは、画像の読み込みエラーを監視し、srcを置き換える非常に単純なディレクティブです。 (Plunker)

HTML:

<img ng-src="smiley.png" err-src="http://google.com/favicon.ico" />

Javascript:

var app = angular.module("MyApp", []);

app.directive('errSrc', function() {
  return {
    link: function(scope, element, attrs) {
      element.bind('error', function() {
        if (attrs.src != attrs.errSrc) {
          attrs.$set('src', attrs.errSrc);
        }
      });
    }
  }
});

NgSrcが空白のときにエラー画像を表示したい場合は、これを追加できます (Plunker)

attrs.$observe('ngSrc', function(value) {
  if (!value && attrs.errSrc) {
    attrs.$set('src', attrs.errSrc);
  }
});

問題は、値が空白の場合、ngSrcはsrc属性を更新しないことです。

252
Jason Goemaat

パーティーに少し遅れましたが、私が構築しているシステムで多かれ少なかれ同じ問題の解決策を思いつきました。

しかし、私の考えは、すべての画像imgタグをグローバルに処理することでした。

ここに示されているerr-srcのような不要なディレクティブでHTMLをペッパー化する必要はありませんでした。かなり頻繁に、特に動的画像の場合、手遅れになるまでそれが欠落しているかどうかはわかりません。画像が欠落している偶然に余分なディレクティブを追加すると、私にはやり過ぎのように思えます。

代わりに、既存のimgタグを拡張します。これは、実際にはAngularディレクティブの目的です。

だから-これは私が思いついたものです。

:これには、.error()を使用しているため、付属のJQlite Angularだけでなく、完全なJQueryライブラリが必要です。

あなたはこれで実際にそれを見ることができます Plunker

ディレクティブは次のようになります。

app.directive('img', function () {
    return {
        restrict: 'E',        
        link: function (scope, element, attrs) {     
            // show an image-missing image
            element.error(function () {
                var w = element.width();
                var h = element.height();
                // using 20 here because it seems even a missing image will have ~18px width 
                // after this error function has been called
                if (w <= 20) { w = 100; }
                if (h <= 20) { h = 100; }
                var url = 'http://placehold.it/' + w + 'x' + h + '/cccccc/ffffff&text=Oh No!';
                element.prop('src', url);
                element.css('border', 'double 3px #cccccc');
            });
        }
    }
});

エラーが発生すると(画像が存在しないか到達できないなどの理由で)、キャプチャして反応します。そもそも画像/スタイルに画像サイズが存在する場合は、画像サイズの取得を試みることもできます。そうでない場合は、自分でデフォルトを設定します。

この例では、代わりに画像にplacehold.itを使用しています。

これで、srcまたはng-srcの使用に関係なく、すべてのイメージが、何もロードされない場合に備えてカバーされています...

48

Jasonソリューションを拡張して、読み込みエラーまたは空のソース文字列の両方のケースをキャッチするには、ウォッチを追加するだけです。

HTML:

<img ng-src="smiley.png" err-src="http://google.com/favicon.ico" />

Javascript:

var app = angular.module("MyApp", []);

app.directive('errSrc', function() {
  return {
    link: function(scope, element, attrs) {

      var watcher = scope.$watch(function() {
          return attrs['ngSrc'];
        }, function (value) {
          if (!value) {
            element.attr('src', attrs.errSrc);  
          }
      });

      element.bind('error', function() {
        element.attr('src', attrs.errSrc);
      });

      //unsubscribe on success
      element.bind('load', watcher);

    }
  }
});
21
user2899845
App.directive('checkImage', function ($q) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            attrs.$observe('ngSrc', function (ngSrc) {
                var deferred = $q.defer();
                var image = new Image();
                image.onerror = function () {
                    deferred.resolve(false);
                    element.attr('src', BASE_URL + '/assets/images/default_photo.png'); // set default image
                };
                image.onload = function () {
                    deferred.resolve(true);
                };
                image.src = ngSrc;
                return deferred.promise;
            });
        }
    };
});

hTMLで:

<img class="img-circle" check-image ng-src="{{item.profileImg}}" />
10
Mehul

画像が404の場合、またはディレクティブが不要な場合は画像がnull空の場合、次のようにng-srcフィルタを使用できます:)

<img ng-src="{{ p.image || 'img/no-image.png' }}" />
10
NeoNe

私はこのようなものを使用しますが、team.logoが有効であることを前提としています。 「team.logo」が設定されていないか空の場合、デフォルトが強制されます。

<img ng-if="team.logo" ng-src="https://api.example.com/images/{{team.logo}}">
<img ng-hide="team.logo" ng-src="img/default.png">
8
evandentremont

そのためにangularも、CSSやJSも必要ありません。必要に応じて、この回答(リンク)をシンプルなディレクティブでラップして、よりシンプルにすることができます。

CSS/HTML(jsなし)のみを使用して壊れた画像を非表示にする方法

2
Nick Steele

ネイティブjavascriptを使用して思いついたソリューションを次に示します。画像が壊れているかどうかを確認し、念のため画像にクラスを追加し、ソースを変更しています。

Quoraの回答から回答の一部を得ました http://www.quora.com/How-do-I-use-JavaScript-to-find-if-an-image-is-broken

app.directive('imageErrorDirective', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element[0].onerror = function () {
                element[0].className = element[0].className + " image-error";
                element[0].src = 'http://img3.wikia.nocookie.net/__cb20140329055736/pokemon/images/c/c9/702Dedenne.png';
            };
        }
    }
});
1
Anselm Marie

コードでフォールバックイメージを宣言できない特別な理由はありますか?

私が理解しているように、あなたはあなたの画像ソースに対して2つの可能なケースを持っています:

  1. 情報を正しく設定<4 =フォールバックイメージ。
  2. 情報を正しく設定== 4 =生成されたURL。

これはアプリで処理する必要があると思います-正しいURLを現在判別できない場合は、代わりにロード/フォールバック/プレースホルダーイメージURLを渡します。

理由は、いつでも表示する正しいURLを明示的に宣言しているため、「失われた」画像がないことです。

1
Alex Osborn

http://angular-ui.github.io/ にあるように、Angular UI Utils 'if statement'ディレクティブを使用して問題を解決することをお勧めします。 。まったく同じことをするために使用しました。

これはテストされていませんが、次のようなことができます。

コントローラーコード:

$scope.showImage = function () {
    if (value1 && value2 && value3 && value4) { 
        return true;
    } else {
        return false;
    }
};

(またはよりシンプル)

$scope.showImage = function () {
    return value1 && value2 && value3 && value4;
};

ビューのHTML:<img ui-if="showImage()" ng-src="images/{{data.value}}.jpg" />

または、もっと簡単に、スコーププロパティを使用することもできます。

コントローラーコード:

$scope.showImage = value1 && value2 && value3 && value4;

ビューのHTML:<img ui-if="showImage" ng-src="images/{{data.value}}.jpg" />

プレースホルダーイメージの場合は、別の同様の<img>タグを追加しますが、ui-ifパラメーターに感嘆符(!)マークを付加し、ngSrcにプレースホルダーイメージへのパスを設定するか、通常のol 'HTMLに従ってsrcname__タグを使用します。

例えば。 <img ui-if="!showImage" src="images/placeholder.jpg" />

明らかに、上記のコードサンプルはすべて、value1、value2、value3、およびvalue4のそれぞれが、4つの情報のそれぞれが不完全なときにnullname__/falsename__と等しくなることを前提としています(したがって、ブール値がtruename__になると仮定します) )。

PS。 AngularUIプロジェクトは最近サブプロジェクトに分割され、ui-ifのドキュメントは現在欠落しているようです(おそらくパッケージのどこかにあります)。ただし、ご覧のとおり使用するのは非常に簡単で、Angular UIプロジェクトにGithubの「問題」を記録して、チームにも指摘しています。

更新: 'ui-if'は、AngularJSコードに統合されているため、AngularUIプロジェクトにありません!ただし、現在「不安定」とマークされているv1.1.xのみ。

1
Matty J

私自身の解決策を思いついた。 srcまたはngSrcが空の場合、およびimgが404を返す場合の両方で画像を置き換えます。

(@Darrenソリューションのフォーク)

directive('img', function () {
return {
    restrict: 'E',        
    link: function (scope, element, attrs) {   
        if((('ngSrc' in attrs) && typeof(attrs['ngSrc'])==='undefined') || (('src' in attrs) && typeof(attrs['src'])==='undefined')) {
            (function () {
                replaceImg();
            })();
        };
        element.error(function () {
            replaceImg();
        });

        function replaceImg() {
            var w = element.width();
            var h = element.height();
            // using 20 here because it seems even a missing image will have ~18px width 
            // after this error function has been called
            if (w <= 20) { w = 100; }
            if (h <= 20) { h = 100; }
            var url = 'http://placehold.it/' + w + 'x' + h + '/cccccc/ffffff&text=No image';
            element.prop('src', url);
        }
    }
}
});
0
andrfas

これにより、ng-srcが存在しないかどうかを確認するために2回だけループできます。そうでない場合はerr-srcを使用します。これにより、ループが継続しなくなります。

(function () {
    'use strict';
    angular.module('pilierApp').directive('errSrc', errSrc);

    function errSrc() {
        return {
            link: function(scope, element, attrs) {
             element.error(function () {
                // to prevent looping error check if src == ngSrc
                if (element.prop('src')==attrs.ngSrc){
                     //stop loop here
                     element.prop('src', attrs.errSrc);
                }              
            });
            }
        }
    }
})();
0