[英]Rendering SVG templates in AngularJS directives
我正在使用SVG和angular.js开展大型项目,并且需要对svg指令模板提供可靠的支持。 不幸的是,当angular渲染模板时,它会创建DOM节点,而不是SVG节点。 我目前的工作是使用jquery.svg自己管理创建和删除节点,但它的限制。 示例: http : //plnkr.co/edit/Xk8wM3?p = preview
我想指令element
是实际的svg元素,而不是一些没有真正做任何事情的虚假DOM元素。 这将让我有效地使用ng-repeat和angular滤镜。
这是需要修复的plunkr: 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;
}
我已经分叉并更新了你的plunker,使它在这里工作。 当有问题的节点通过角度从文档中分离出来进行处理时,你的函数'makeNode'有时会抛出错误。 使用0 ms的超时可以延迟执行,以使父节点可用。 另外,我使用链接函数来执行所有操作,因为编译函数每ng-repeat只执行一次,但我们需要重复多次。 您可以在Angular Directive页面上的“编译和链接之间的区别”部分下阅读有关编译和链接功能之间差异的更多信息。
这是相关代码:
/* 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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.