此刻,我已经成功导入了要在其上添加鱼眼效果的SVG。我想做类似于this example的事情。我看过那里使用的代码如下:
var path = svg.selectAll("path")
.attr("d", line);
svg.on("mousemove", function() {
fisheye.center(d3.mouse(this));
path.attr("d", function(d) { return line(d.map(fisheye)); });
});
但是,我不像以前那样使用线,但是我确实有像它们一样的路径。老实说,我不太确定为什么在这样的代码中使用d3.line。但是我现在是这样的:
d3.xml('log.svg')
.then(data => {
d3.select('body').node().append(data.documentElement)
var fisheye = d3.fisheye.circular()
.radius(200)
.distortion(2);
var svg = d3.select("body").select("svg g")
var path = svg.selectAll("path")
.attr("d");
svg.on("mousemove", function() {
fisheye.focus(d3.mouse(this));
path.attr("d", function(d) {
return (d.map(fisheye)) // Not sure about this part yet.
});
});
});
控制台给我以下错误:
未捕获的TypeError:path.attr不是函数
这发生在此行上:
path.attr("d", function(d) {
return (d.map(fisheye)) // Not sure about this part yet.
});
有人知道为什么会出现这种错误吗?它与工作版本没有太大不同吗?
答案 0 :(得分:0)
您必须更改:
var path = svg.selectAll("path")
.attr("d");
到
var path = svg.selectAll("path");
(还请注意,您有时用分号来结束语句,有时则不用分号)
此错误的原因很重要,因为它是d3.js中经常使用的重要代码设计。
要设置对象的属性/属性/行为,您不能直接设置它们。而是调用设置它们的函数,这样内部逻辑可以避免副作用。
这些 setter函数通常还会做两件事:
第二个项目符号允许您进行优雅的方法链接:
因此,如果要在一个对象上设置三个属性,则无需编写
let obj = *object*;
obj.method1(‘a’);
obj.method2(‘b’);
obj.method3(‘c’);
或
let obj = *object*;
obj = obj.method1(‘a’);
obj = obj.method2(‘b’);
obj = obj.method3(‘c’);
您可以改为:
let obj = *object*.method1(‘a’).method2(‘b’).method3(‘c’);
在选择上,因为设置了很多属性,所以您经常不应用此方法链接!
正如我提到的,为方便起见,可以将相同的方法用作 getter 函数:
// calling method without argument returns its value
obj.method1(); // returns ‚a‘ !! not the obj!!
这意味着在应用getter函数之后,您将无法再进行方法链接,因为“ a”没有 method2 等。
对于 selections ,除了 selection.attr()或 selection.style()决定是根据第二个参数设置 / 获取。
回到您的示例:
var path = svg.selectAll("path")
.attr("d");
是getter函数,返回已(或尚未分配)给元素的d属性的字符串。
相反:
var path = svg.selectAll("path");
返回所有路径的选择,因此, 设置功能:
var path = svg.selectAll("path")
.attr("d", „*your path string*“);
请注意,您可以在鱼眼示例本身中看到的使用 getter,setter和方法链的代码设计实现:
fisheye.center = function(_) {
if (!arguments.length) return center;
center = _;
return fisheye;
};
return rescale();
另请参阅Mike Bostocks excellent article有关可重复使用的代码,他在其中解释了此代码设计。