我想在联合使用angularjs和d3js时报告一个相当奇怪的行为。以下plunker说明了它:Plunker
这是执行大部分工作的指令:
.directive('element1', function() {
return {
restrict: 'E',
replace: true,
template: '<svg></svg>',
link: function (scope, element, attrs) {
var rootElmt = d3.select(element[0]);
rootElmt.append("g")
.selectAll("text")
.data(["Hello World"])
.enter()
.append("text")
.attr("x", 20)
.attr("y", 20)
.text(function(d) {
return d;
});
rootElmt.selectAll("text")[0]
.forEach(function(d) {
console.log("text length: ", d.getComputedTextLength());
});
}
}
});
你肯定会注意到自定义元素指令element1在获得的结果的基础上做了很多不必要的工作 - 实际上,我在一个更复杂的软件中发现了一个问题的核心,这个设备是在某种程度上需要。
plunker产生预期的结果,即显示SVG文本字符串,并记录应用于后者的getComputedTextLength()的结果。 plunker使用angularjs v1.2.0rc3。
现在,如果您注释1.2.0rc3脚本加载子句,并取消注释1.2.17(即一个相当新版本)的子句,则代码会遇到错误,由getComputedTextLength未定义引起。
此错误可以追溯到文本对象的属性:虽然SVGTextElement对象提供的角度较旧版本(即来自SVG原型链),但较新的版本会带来HTMLUnknownElement对象 - 导致明显缺少getComputedTextLength方法。
这可能是angularjs和d3之间错综复杂的互动的原因吗?也许我的指令代码不符合最近的angularjs最佳实践?
感谢您提前寻求帮助!
答案 0 :(得分:1)
问题的根源在于您在Angular模板中创建SVG节点,而不是推迟到D3代码在指令中创建它:
template: '<svg></svg>',
这似乎与Angular issue #7383有关,似乎已在版本1.2.16中引入。
我看到1.3分支(尚未发布)即将推出feature #7265来恢复此支持:
以前,模板始终被认为是有效的HTML节点。在某些情况下,最好使用SVG或MathML或其他语言。
要在Angular 1.2.x中解决此问题,您只需从指令中删除模板属性,然后从D3代码创建SVG节点:
// create it here instead:
var rootElmt = d3.select(element[0]).append('svg');