在Angularjs指令中包含SVG模板

mkl*_*kly 19 javascript svg angularjs

<div ng-app="testrectApp">
<svg>
    <rect height="10" width="10" style="fill: #00ff00" />
    <testrect />
</svg>
</div>
Run Code Online (Sandbox Code Playgroud)

这是我的指示

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

但这就是元素最终看起来像在浏览器中.填充两次不是拼写错误.

<rect top="20" left="20" height="10" width="10" style="fill: #ff00ff;fill: #ff00ff"></rect>
Run Code Online (Sandbox Code Playgroud)

这是一个jsfiddle http://jsfiddle.net/RG2CF/

是我想做的不可能还是我做错了什么?

谢谢

编辑:我应该补充一点,这个问题可能与模板svg rect被命名为xhtml而不是svg的事实有关,但我不确定如何强制这个或命名空间它回到svg,如果实际上是解决方案.

Jos*_*ger 29

templateNamespace您可以设置一个属性svg:

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

这是文档的链接.


Jas*_*ore 19

Angular 1.3更新!

我在下面的原始答案充其量只是一个巨大的黑客.你应该做的是更新Angular 1.3并templateNamespace:'svg'在你的指令上设置属性.下面以@Josef Pfleger的答案为例:在Angularjs指令中包含SVG模板


老答案

如果将来遇到这种情况,我可以创建一个与svg模板一起使用的编译功能.它现在有点难看,所以非常感谢重构帮助.

实例:http://plnkr.co/edit/DN2M3M?p = preview

app.service('svgService', function(){

    var xmlns = "http://www.w3.org/2000/svg";
    var compileNode = function(angularElement){
      var rawElement = angularElement[0];

      //new lines have no localName
      if(!rawElement.localName){
        var text = document.createTextNode(rawElement.wholeText);
        return angular.element(text);
      }
      var replacement = document.createElementNS(xmlns,rawElement.localName);
      var children = angularElement.children();

      angular.forEach(children, function (value) {
        var newChildNode = compileNode(angular.element(value));
        replacement.appendChild(newChildNode[0]);
      });

      if(rawElement.localName === 'text'){
        replacement.textContent = rawElement.innerText;
      }

      var attributes = rawElement.attributes;
      for (var i = 0; i < attributes.length ; i++) {
        replacement.setAttribute(attributes[i].name, attributes[i].value);
      }

      angularElement.replaceWith(replacement);

      return angular.element(replacement);
    };

    this.compile = function(elem, attrs, transclude) {
      compileNode(elem);

      return function postLink(scope, elem,attrs,controller){
//        console.log('link called');
      };
    }
  })
Run Code Online (Sandbox Code Playgroud)

用例:

app.directive('ngRectAndText', function(svgService) {
  return {
    restrict: 'E',
    template: 
    '<g>'
    + '<rect x="140" y="150" width="25" height="25" fill="red"></rect>'
    + '<text x="140" y="150">Hi There</text>'
    + '</g>'
    ,
    replace: true,
    compile: svgService.compile
  };
});
Run Code Online (Sandbox Code Playgroud)


Ben*_*esh 4

目前 SVG 标签不支持动态添加标签,至少在 Chrome 中是这样。它甚至不显示新的矩形,即使您直接使用 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" />');
});
Run Code Online (Sandbox Code Playgroud)

我的猜测是,无论您以这种方式做什么,您都会看到一些非常疯狂的行为。看来这是浏览器的问题,而不是 Angular 的问题。我建议将其报告给 Chromium 项目

编辑:

如果您以编程方式通过 DOM 100% 添加它,它看起来可能会起作用:How to make Chrome redraw SVGdynamically linked content?