7

我有兴趣通过组合包装在 Angular.js 指令中的可重用图形元素来构建复合 SVG。例如我可能有:

<div ng-app="svgApp">
  <canvas>
    <drawing ng-repeat="i in [1,2,3]" cy="{{i * 40}}"></drawing>
  </canvas>
</div>

我在哪里定义以下指令:

  .directive('canvas', function () {
    return {
      template: '<svg height=200 width=100 ng-transclude></svg>',
      restrict: 'E',
      replace: true,
      transclude: true
    };
  })

  .directive('drawing', function () {
    return {
      template: '<circle cx=50 r=15></circle>',
      restrict: 'E',
      replace: true
    };
  })

问题是 SVG 元素似乎没有被正确地嵌入。在另一个 StackOverflow 问题中似乎有一个线索,这主要是因为 SVG 节点没有在 Angular.js 中正确创建。

在进一步探索之后,我发现了这个解决方案,它涉及使用辅助函数将相关的 DOM 元素替换为正确创建的 SVG 节点,例如:

  .value('createSVGNode', function(name, element, settings) {
      var namespace = 'http://www.w3.org/2000/svg';
      var node = document.createElementNS(namespace, name);
      for (var attribute in settings) {
        var value = settings[attribute];
        if (value !== null && !attribute.match(/\$/) && (typeof value !== 'string' || value !== '')) {
            node.setAttribute(attribute, value);
        }
      }
      return node;
  });

但是,我需要在任何地方都使用它似乎是不可取的,并且我希望将解决方法尽可能地保留在 bug 的本地,直到它被修复。

我的问题是以下是否是一个合理的解决方法:

angular.forEach(['circle', ...], function (svgElem) {

  svgModule

    .directive(svgElem, function (createSVGNode) {
      return {
        restrict: 'E',
        link: function(scope, element, attrs) {
          var node = createSVGNode(svgElem, element, attrs);
          angular.element(node).append(element[0].childNodes);
          element.replaceWith(node);
        }
      };
    });

});

这适用于Plunker

以这种方式重新定义现有的 SVG 元素指令对我有效吗?

4

1 回答 1

6

如果您无法将代码移至 AngularJS 1.3 的活动开发技巧,则上述方法是一种可能的方法,其中解决了包含不同命名空间(例如 SVG 或 MathML)的元素的问题

链接的Plunker演示了如何使用修复程序更新您的代码。关键是在指令定义对象中添加了一个新的“templateNamespace”键:

  .directive('svgInternal', function () {
    return {
      templateNamespace: 'svg',
      template: '<g><rect height="25" width="25" /><text x="30" y="20">Hello, World</text></g>',
      restrict: 'E',
      replace: true
    };
  })

以下标记演示了正在使用的 SVG 类型指令:

  <svg height="30">
    <svg-internal></svg-internal>
  </svg>

编辑:自 1.3.beta.19 起,“type”已更改为“templateNamespace”。

于 2014-06-27T01:03:24.967 回答