【问题标题】:Angular.js updating SVG templates in directivesAngular.js 在指令中更新 SVG 模板
【发布时间】:2013-12-28 13:24:02
【问题描述】:

不久前,我询问了“Angular.js rendering SVG templates in directives”,我在其中用 SVG 节点替换了 Angular 在渲染模板时生成的 DOM 节点。我得到了一个为我回答的回复,但我意识到我丢失了 angular 的所有数据绑定。

查看 Plunkr(点击更新):http://plnkr.co/edit/HjOpqc?p=preview

如何将这些 DOM 节点替换为 SVG 节点,并保持我的角度绑定完好无损?我尝试使用 $compile 使其工作(就像我对常规 html 所做的那样),但它只是不工作。

代码:

var svgNS = 'http://www.w3.org/2000/svg';
app.directive('path', ngSvg('path'));
app.directive('g', ngSvg('g'));

function ngSvg(type) {
  return function($timeout, $compile) {
    return {
      restrict: 'E',
      link: function(scope, el, attr) {
        //skip nodes if they are already svg
        if (el[0].namespaceURI === svgNS) {
          return;
        }

        // I would expect the chunk of code below to work,
        // but it does not with ng-repeat

        // var newAttr = {};
        // _.each(el[0].attributes, function(at) {
        //   newAttr[at.nodeName] = at.value;
        // });

        // var path = makeNode(type, el, newAttr);
        // var parent = path.cloneNode(true);

        // $compile(parent)(scope);

        // var children = el.children();
        // $(parent).append(children);

        // $timeout(function() {
        //   el.replaceWith(parent);
        // })


        // this works for rendering, but does not update the svg elements
        // when update is clicked
        $timeout(function() {
          var newAttr = {};
          _.each(el[0].attributes, function(at) {
            newAttr[at.nodeName] = at.value;
          });

          var path = makeNode(type, el, newAttr);
          var parent = path.cloneNode(true);


          var children = el.children();
          $(parent).append(children);
          el.replaceWith(parent);
        });
      }
    }
  }
}

/* Create a shape node with the given settings. */
function makeNode(name, element, settings) {
  // var ns = 'http://www.w3.org/2000/svg';
  var node = document.createElementNS(svgNS, name);
  for (var attribute in settings) {
    var value = settings[attribute];
    if (value !== null && value !== null && !attribute.match(/\$/) &&
      (typeof value !== 'string' || value !== '')) {
      node.setAttribute(attribute, value);
    }
  }
  return node;
}

【问题讨论】:

  • 你能在哪里解决这个问题?好奇您是否能够使用 Angular 1.3.x 来实现这一点,因为它修复了很多 SVG 问题,包括在模板声明中定义 SVG。
  • 我确实看到 angular 1.3 解决了 svg 问题。从那以后我就离开了这个项目并且没有检查过。如果您有任何工作,请告诉我,我会更新问题和/或将您的答案标记为正确。
  • @JasonMore 我已经包含了关于您之前所说的 cmets 的答案。如果这个功能是你在早期版本的 Angular 中试图实现的功能,能否告诉我?
  • 感谢@salniro 的回答。不幸的是,我不再参与这个项目,但确实看到现在完全支持 svg。感谢您回答问题

标签: javascript angularjs svg angularjs-directive angularjs-ng-repeat


【解决方案1】:

这个问题在 Angular 1.3 中得到解决,这里是一些自定义 svg 指令的实现,具有您期望从 Angular 指令获得的行为。现在有一个特殊要求是指令声明如下templateNamespace: 'svg'

还请注意,我正在覆盖一些保留属性,例如,xheight<rect/> 相关。要保留对这些的更多控制权,您可以利用ng-attr'<rect ng-attr-width="{{ ngWidth }}" />

JSFiddle Link

这是一个自定义的<rect/><circle/>

app.directive('ngRect', [function () {
    return {
        templateNamespace: 'svg',
        replace: true,
        template: '<rect ng-attr-width="{{ ngWidth }}" ng-attr-height="{{ ngHeight }}" ng-attr-x="{{ ngX }}" ng-attr-y="{{ ngY }}" ng-click="ngRectClick()"/>',
        scope: {
            'ngHeight': '=',
            'ngWidth': '='
        },
        link: function (scope, elem, attrs) {
            scope.ngRectClick = function() {
                console.log(elem);
            }
        }
    }
}]);

app.directive('ngCircle', [function () {
    return {
        templateNamespace: 'svg',
        replace: true,
        template: '<circle ng-attr-cx="{{ ngCx }}" ng-attr-cy="{{ ngCy }}" ng-attr-r="{{ ngR }}" ng-attr-fill="{{ ngFill }}" ng-click="ngCircleClick()"/>',
        scope: {
            'ngCx': '=',
            'ngCy': '=',
            'ngR': '=',
            'ngFill': '='
        },
        link: function (scope, elem, attrs) {
            scope.ngCircleClick = function() {
                console.log(elem);
            }
        }
    }
}]);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 2013-11-03
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    相关资源
    最近更新 更多