19
<div ng-app="testrectApp">
<svg>
    <rect height="10" width="10" style="fill: #00ff00" />
    <testrect />
</svg>
</div>

そして、これは私の指示です

module.directive('testrect', function() {
    return {
        restrict: 'E',
        template: '<rect top="20" left="20" height="10" width="10" style="fill: #ff00ff" />',
        replace: true
    };
});

しかし、これは要素がブラウザーでどのように見えるかです。2回塗りつぶすのはタイプミスではありません。

<rect top="20" left="20" height="10" width="10" style="fill: #ff00ff;fill: #ff00ff"></rect>

ここにjsfiddleがありますhttp://jsfiddle.net/RG2CF/

私がやろうとしていることは不可能ですか、それとも何か間違っていますか?

ありがとう

編集: この問題は、テンプレート svg rect が svg ではなく xhtml に名前空間化されているという事実に関係している可能性があることを追加する必要がありますが、これまたは名前空間を強制的に svg に戻す方法がわかりません。ソリューション。

4

5 に答える 5

29

templateNamespace設定できるプロパティがありますsvg

module.directive('testrect', function() {
    return {
        restrict: 'E',
        templateNamespace: 'svg',
        template: '<rect .../>',
        replace: true
    };
});

ここにドキュメントへのリンクがあります。

于 2014-12-28T10:01:52.167 に答える
4

SVG に innerHTML shim (別名「innerSVG」) を使用すると、Jason More の洞察に満ちた回答に代わるものとして、このパズルの別のピースが提供されます。この innerHTML/innerSVG アプローチは、Jason の回答のような特別なコンパイル関数を必要としないため、よりエレガントだと思いますが、少なくとも 1 つの欠点があります。「replace: true」がディレクティブに設定されている場合は機能しません。(innerSVG アプローチについては、こちらで説明しています: Is there some innerHTML replacement in SVG/XML? )

// Inspiration for this derived from a shim known as "innerSVG" which adds
// an "innerHTML" attribute to SVGElement:
Object.defineProperty(SVGElement.prototype, 'innerHTML', {
  get: function() {
    // TBD!
  },
  set: function(markup) {
    // 1. Remove all children
    while (this.firstChild) {
      this.removeChild(this.firstChild);
    }

    // 2. Parse the SVG
    var doc = new DOMParser().parseFromString(
        '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
        + markup
        + '</svg>',
        'application/xml'
    );

    // 3. Import the parsed SVG and grab the childNodes
    var contents = this.ownerDocument.importNode(doc.documentElement, true).childNodes;

    // 4. Append the childNodes to this node
    // Note: the following for loop won't work because as items are appended,
    // they are removed from contents (you'd end up with only every other
    // element getting appended and the other half remaining still in the
    // original document tree):
    //for (var i = 0; i < contents.length; i++) {
    //  this.appendChild(contents[i]);
    //}
    while (contents.length) {
      this.appendChild(contents[0]);
    }
  },
  enumerable: false,
  configurable: true
});

試すプランカーは次のとおりです。http://plnkr.co/edit/nEqfbbvpUCOVC1XbTKdQ?p=preview

これが機能する理由: SVG 要素は XML 名前空間http://www.w3.org/2000/svg内に存在するため、DOMParser() で解析するか、createElementNS() でインスタンス化する必要があります (どちらも名前空間を適切に設定できます。SVG を使用するこのプロセスが HTML と同じくらい簡単であればいいのですが、残念ながらそれらの DOM 構造は微妙に異なるため、独自の innerHTML shim を提供する必要があります。さて、これで「replace: true」も動作するようになれば、それは良いことです!

編集:appendChild() ループを更新して、ループの実行中に内容が変更される回避策にしました。

于 2013-07-02T09:43:43.387 に答える
4

現在、少なくとも Chrome では、SVG タグはタグの動的追加をサポートしていません。新しい四角形は表示されません。また、DOM または JQuery.append() で直接追加したとしても表示されません。JQueryでそれをやろうとしているだけを見てください

// this doesn't even work right. Slightly different error than yours.
$(function() {
    $('svg').append('<rect top="20" left="20" height="10" width="10" style="fill: #ff00ff" />');
});

私の推測では、この方法で何をしても、本当にクレイジーな動作が見られると思います。Angular の問題ではなく、ブラウザの問題のようです。Chromium プロジェクトに報告することをお勧めします

編集:

DOM を介してプログラムで 100% 追加するとうまくいくようです: How to make Chrome redraw SVG dynamic added content?

于 2012-11-30T16:35:14.920 に答える