web-dev-qa-db-ja.com

AngularJS ng-hrefおよびsvg xlink

角度付きのxml名前空間付き属性の使用に関する入力をお願いします。

問題はangularには、angularが式を解析したときにhrefやsrcなどの属性の書き込みを処理するためのいくつかのディレクティブが付属しています(そうでない場合、ブラウザは_{{mymodel.myimage}}_をURLとしてロード)

https://github.com/angular/angular.js/blob/master/src/ng/directive/booleanAttrs.js#L329

私が直面している問題は、angularを使用してD3と一緒にsvgを出力していることです。angularには_xlink:href_行き詰まりました。

Xlink:hrefを出力するカスタムディレクティブを作成しました

_app.directive('ngXlinkHref', function () {
  return {
    priority: 99,
    restrict: 'A',
    link: function (scope, element, attr) {
      var attrName = 'xlink:href';
      attr.$observe('ngXlinkHref', function (value) {
        if (!value)
          return;

        attr.$set(attrName, value);
      });
    }
  };
});
_

完全なデモ: http://plnkr.co/edit/cMhGRh

しかし、要素にxlink:hrefを手動で追加しないと、svg画像がレンダリングされないようです。

angularと一緒にxml名前空間/ svgを最適に処理する方法についての提案は、大歓迎です。

39
Leon Radley

ng-attr-<some attribute>を使用できます

ng-attr-xlink:href="{{xxx}}"は私に適しています。


空のxlink:href=""も初期値として必要であることに注意してください。 –デレク・スー

59
Derek Hsu

私のように、画像をsvgに追加する方法を探している場合は、次のように追加できます。

xlink:href="" ng-href="{{ foo }}"

例:

http://jsbin.com/sigoleya/1/edit?html,js,output

私が解決策を見つけた場所:

https://github.com/angular/angular.js/issues/7697

19
Tiagojdferreira

モデルに関連付けられている_xlink:href_の値を出力しようとすると、同様の問題が発生しました。 _<option>_コントロールでユーザーが選択した_<select>_に基づいて、_xlink:href_要素の_<use>_属性を介して動的SVGアイコンを表示しようとしました。

AngularJSのGitHubの問題で これに関するスレッド を見つけました。そこでの議論に基づいて、実行可能な回避策が存在するため、バックログマイルストーンに移動することで修正を効果的にまとめたようです。

最終的に私のために機能したのは、このJSBinに触発されました。

http://jsbin.com/sigoleya/1/edit?html,js,output

これが私のテンプレートで使用したコードです。

_<svg class="icon" data-ng-class="category.iconName">
  <use xlink:href="" data-ng-href="{{'#' + category.iconName}}">
</svg>
_

たとえば、_category.iconName_の_icon-music_を指定すると、Angularは_xlink:href_を_#icon-music_に動的に設定し、_<svg id="icon-music">_を参照します同じページのさらに上の要素。

他の人が指摘したように、重要なのは、ngHrefディレクティブを呼び出す要素に空の_xlink:href=""_属性を設定することです。属性の順序は重要ではないようです。 _ng-attr-xlink:href="{{xxx}}"_(Derek Hsuの回答で述べたように)を使用してもうまくいきませんでした。

これはすべてAngular 1.3.36。

10
Bungle

私は次のモジュールで同じ問題を解決しました:

SVGのモジュール:

var app = angular.module('Svgs', []);

angular.forEach([
    { ngAttrName: 'ngXlinkHref', attrName: 'xlink:href' },
    { ngAttrName: 'ngWidth', attrName: 'width' },
    { ngAttrName: 'ngHeight', attrName: 'height' }
], function (pair) {

    var ngAttrName = pair.ngAttrName;
    var attrName = pair.attrName;

    app.directive(ngAttrName, function (IeHelperSrv) {

        return {

            priority: 99,

            link: function (scope, element, attrs) {

                attrs.$observe(ngAttrName, function (value) {

                    if (!value) return;

                    attrs.$set(attrName, value);
                    if (IeHelperSrv.isIE) element.prop(attrName, value);
                });
            }
        };
    });
});

IE検出用モジュール:

angular.module('IeHelper', []).factory('IeHelperSrv', function () {

    return {
        isIE: checkForIE.isIE,
    }
});

var checkForIE = {
    init: function () {
        this.isIE = (navigator.userAgent.indexOf('MSIE') != -1);
    }
};

checkForIE.init();

HTML:

<!-- image has initial fake source, width and height to force it to render -->
<image xlink:href="~/Content/Empty.png" width="1" height="1"
    ng-xlink-href="{{item.imageSrc}}"
    ng-width="{{item.width}}" ng-height="{{item.height}}"
    ng-cloak
    />
6
Danny Varod

HTML5モードのAngular/Angular UIルーターが原因でこの問題が発生している他の人のために、svgスプライトアイコンがxlink:href属性とタグで機能するようにする簡単な修正を思いつきました。

Gist is here: https://Gist.github.com/planetflash/4d9d66e924aae95f7618c03f2aabd4a

app.run(['$rootScope', '$window', function($rootScope, $window){
 $rootScope.$on('$locationChangeSuccess', function(event){
    $rootScope.absurl = $window.location.href;
});

<svg><use xlink:href="{{absurl+'#svgvID'}}"></use></svg>
2
Paul Thomas

これには、思ったよりも時間がかかりました。約20〜30分。

私が正しく理解していれば、画像要素の読み込みに失敗するとその要素は今後役に立たなくなりますになります。 @GeekyMonkeyが言っているのと同じようなことだと思います。 angularバインディングシステムが最初にxlink:hrefをnullに設定した場合、将来有効な値があったとしても、Image要素は機能しなくなります。

これが解決策です。ng-ifディレクティブを使用して、image要素をg要素内にラップしたことに注意してください。これにより、正しい値が使用可能な場合にのみイメージにバインドします。

<g ng-if="vm.svgMap.background != null">
    <image
        ng-attr-xlink:href="{{vm.svgMap.background.image | trusted}}"
        ng-attr-width="{{vm.svgMap.background.width}}"
        ng-attr-height="{{vm.svgMap.background.width}}"

        xlink:href=""

        width="1"
        height="1"
        x="0"
        y="0"></image>
</g>

他の人が言ったように、属性の順序も重要です。 angularJSが画像要素をバインドできるようにするために、そのリソースも信頼する必要があります。これは、フィルター(xlink:href属性にあるもの)を通じて行いました。

(function() {
    'use strict';

    angular.module('myTool').filter('trusted', TrustedFilter);

    function TrustedFilter($sce) {
        return function(url) {
            return $sce.trustAsResourceUrl(url);
        };
    };
}());
0

私はAjaxを使用してsvgスプライトシートをページにロードしていたときにこの問題に遭遇しました。スプライトシートがロードされる前にページ上にaがあった場合、それは失敗し、スプライトシートが使用可能になると解決しません。スプライトシートが読み込まれた後にdomに追加されたものは問題ありませんでした。スプライトシートの読み込みが完了するまで、アイテムをdomに入れるのを遅らせなければなりませんでした。

これはIOSにのみ影響しました。他のすべてのブラウザは順序を気にしませんでした。

0
GeekyMonkey