渲染AngularJS指令SVG模板 [英] Rendering SVG templates in AngularJS directives

查看:299
本文介绍了渲染AngularJS指令SVG模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作与SVG和angular.js一个大型项目,需要SVG指令模板坚实的支持。不幸的是,当角呈现模板,它创建DOM节点,而不是SVG节点。我目前的解决办法是管理创建和使用jquery.svg删除节点自己,但它来它限制。例如: http://plnkr.co/edit/Xk8wM3?p=$p$pview

我想有指令元素是实际的SVG元素,而不是一些虚假的DOM元素并没有真正做任何事情。这将让我用NG-重复,有效地角器。

下面是需要固定plunkr: http://plnkr.co/edit / BPvGjf?p = preVIEW

HTML

 < SVG>
  <! - 活泉这一件作品 - >
  <形状D =M0,0L250,0L250,250L0,250z补=绿色>< /形状>  <! - 嵌套指令不起作用 - >
  &所述;组>
    <形状D =M0,0L150,0L150,150L0,150z补=红色>< /形状>
    <形状D =M0,0L100,0L100,100L0,100z补=橙色>< /形状>
  < /组>  <! - 纳克重复不起作用 - >
  <形状D ={{square.path}}补={{square.color}}NG重复=,在广场广场|排序依据:'订单'>< /形状>
< / SVG>

的JavaScript

  VAR应用= angular.module('plunker',[]);app.controller('MainCtrl',函数($范围){
  $ scope.squares = [{
    路径:M0,0L50,0L50,50L0,50z
    颜色:'蓝',
    顺序:2
  },{
    路径:M0,0L75,0L75,75L0,75z
    颜色:'紫',
    顺序:1
  }];
});app.directive('组',函数($编译){
  返回{
    限制:'E',
    transclude:真实,
    编译:功能(tElement,对tattr,transclude){
      VAR路径= makeNode('G',tElement,对tattr);      tElement.append(path.cloneNode(真));      返回功能(范围,元素){
        transclude(范围,功能(克隆,innerScope){
          element.append($编译(克隆)(innerScope));
        })
      }
    }
  }
});app.directive('形',函数(){
  返回{
    限制:'E',
    编译:功能(tElement,对tattr){
      VAR路径= makeNode('路径',tElement,对tattr);      tElement.replaceWith(path.cloneNode(真));      返回功能(范围,元素){      }
    }
  }
})/ *创建具有给定设置的形状节点。 * /
功能makeNode(名称,元素,设置){
  变种的svg = $(元件)。家长('SVG')[0];
  变种父= $(元件).parent()[0];
  VAR厂= $('#工厂')[0] || $('身体')追加('< SVG ID =工厂>< / SVG>')。找到('#工厂')[0];
  VAR NS ='http://www.w3.org/2000/svg';  //我使用工厂在这里创建节点然后试图克隆
  //入新的SVG,但由于角节点创建子 - 首先,它没有工作  VAR节点= parent.ownerDocument.createElementNS(NS,名);
  对(在设置var属性){
    VAR值=设置[属性]
    如果(价值== NULL和放大器;!&安培;价值== NULL和放大器;!&安培;!attribute.match(/ \\ $ /)及和放大器;
      (typeof运算值!=='串'||价值!=='')){
      node.setAttribute(属性值);
    }
  }
  parent.appendChild(节点);
  返回节点;
}


解决方案

我已付出和更新您的plunker,使其工作的此处。你的函数'makeNode有时抛出的错误,当有问题的节点,是从文件由角分开进行处理。使用0毫秒的超时确实延缓执行就足以让父节点可用的把戏。
另外,我现在用的链接功能来完成所有的操作,因为编译功能每纳克重复执行一次,但我们需要重复的次数。你可以阅读更多有关编译和链接功能之间的第编译和链接之间的区别在角指令的区别页。

下面是相关code:

  / *创建具有给定设置的形状节点。 * /
功能makeNode(名称,元素,设置){
  VAR NS ='http://www.w3.org/2000/svg';
  VAR节点=与Document.createElementNS(NS,名);
  对(在设置var属性){
    VAR值=设置[属性]
    如果(价值== NULL和放大器;!&安培;价值== NULL和放大器;!&安培;!attribute.match(/ \\ $ /)及和放大器;
      (typeof运算值!=='串'||价值!=='')){
      node.setAttribute(属性值);
    }
  }
  返回节点;
}

I'm working on a large project with SVG and angular.js, and need solid support for svg directive templates. Unfortunately when angular renders the templates, it creates DOM nodes, not SVG nodes. My current work around is to manage creating and deleting the nodes myself using jquery.svg, but its coming to it limits. Example: http://plnkr.co/edit/Xk8wM3?p=preview

I would like to have the directives element be the actual svg element, not some faux DOM element that doesn't really do anything. This will let me use ng-repeat and angular filters effectively.

Here is the plunkr that needs fixing: http://plnkr.co/edit/BPvGjf?p=preview

html

<svg>
  <!--woot this one works-->
  <shape d="M0,0L250,0L250,250L0,250z" fill="green"></shape>

  <!--nesting directives doesn't work-->
  <group>
    <shape d="M0,0L150,0L150,150L0,150z" fill="red"></shape>
    <shape d="M0,0L100,0L100,100L0,100z" fill="orange"></shape>
  </group>

  <!--ng repeat doesn't work-->
  <shape d="{{square.path}}" fill="{{square.color}}" ng-repeat="square in squares | orderBy:'order'"></shape>
</svg>

javascript

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

app.controller('MainCtrl', function($scope) {
  $scope.squares = [{
    path: "M0,0L50,0L50,50L0,50z",
    color: 'blue',
    order: 2
  }, {
    path: "M0,0L75,0L75,75L0,75z",
    color: 'purple',
    order: 1
  }];
});

app.directive('group', function($compile) {
  return {
    restrict: 'E',
    transclude: true,
    compile: function(tElement, tAttr, transclude) {
      var path = makeNode('g', tElement, tAttr);

      tElement.append(path.cloneNode(true));

      return function(scope, element) {
        transclude(scope, function(clone, innerScope) {
          element.append($compile(clone)(innerScope));
        })
      }
    }
  }
});

app.directive('shape', function() {
  return {
    restrict: 'E',
    compile: function(tElement, tAttr) {
      var path = makeNode('path', tElement, tAttr);

      tElement.replaceWith(path.cloneNode(true));

      return function(scope, element) {

      }
    }
  }
})

/* Create a shape node with the given settings. */
function makeNode(name, element, settings) {
  var svg = $(element).parents('svg')[0];
  var parent = $(element).parent()[0];
  var factory = $('#factory')[0] || $('body').append('<svg id="factory"></svg>').find('#factory')[0];
  var ns = 'http://www.w3.org/2000/svg';

  // I've tried using the factory here to create the node then clone
  // it into the new svg, but since angular nodes are created child-first, it didn't work

  var node = parent.ownerDocument.createElementNS(ns, 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);
    }
  }
  parent.appendChild(node);
  return node;
}

解决方案

I have forked and updated your plunker to make it work here. Your function 'makeNode' was throwing error sometimes when the node in question was detached from document by angular for processing. Using a timeout of 0 ms does the trick of delaying the execution just enough to make the parent node available. Also, I am using the linking function to do all manipulation because the compile function executes only once per ng-repeat but we need it repeated number of times. You can read more about the difference between compile and linking functions under 'The difference between Compile and Link' section on Angular Directive page.

Here is the relevant code:

/* 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(ns, 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;
}

这篇关于渲染AngularJS指令SVG模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆