我在多个SO帖子中多次看到过这个问题,虽然发布类似于重复的内容感觉不对,但这个错误似乎出现了很多不同的原因,因此每个问题都与持续。所以我们在这里解决我的问题:
这是我的代码;
window.onload = function () {
var width = 750,
height = 750,
counter = 0;
var force = d3.layout.force()
.size([width, height]);
d3.csv("Data/BubbleData.csv", function (error, links) {
var X = d3.scale.linear()
.domain([0, width])
.range([0, width]);
var Y = d3.scale.linear()
.domain([0, height])
.range([height, 0]);
var zoom = d3.behavior.zoom()
.x(X)
.y(Y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
//handle zooming
function zoomed() {
circles.attr("transform", transform);
}
function transform(d) {
return "translate(" + X(d[0]) + "," + Y(d[1]) + ")";
};
var svg = d3.select("#GraphDiv")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.call(d3.behavior.zoom().x(X).y(Y).scaleExtent([1, 10]).on("zoom", zoom))
.on("dblclick.zoom", null);
var rect = svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all");
var color = d3.scale.category10();
var edges = [],
nodesByNames = {};
//create the nodes
links.forEach(function (link) {
link.App_No = nodeByName(link.App_No);
link.Server_No = nodeByName(link.Server_No);
edges.push({ source: link.App_No, target: link.Server_No })
});
var nodes = d3.values(nodesByNames);
//create container for all to go in
var container = svg.append("g")
.attr("class","container");
//create the links
var link = container.append("g")
.attr("class","LineGroup")
.selectAll(".link")
.data(edges)
.enter().append("line")
.attr("class", "link");
//define mouse behaviour for nodes
var drag = force.drag()
.on("dragstart", function (d) { d3.select(this).select("circle").classed("fixed", d.fixed = true); });
//create the nodes circles
var node = container.append("g")
.attr("class","circleGroup")
.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.call(drag);
var circles = node.append("circle")
.attr("r", 10)
.attr("class", "circle")
.attr("fill", function (d) { return color(d.group); })
.on("dblclick", function (d) { d3.select(this).classed("fixed", d.fixed = false); });
var labels = node.append("text")
.attr("x", 12)
.attr("y", ".35em")
.text(function (d) { return d.Name; });
force
.nodes(nodes)
.links(edges)
.linkDistance(50)
.charge(-100)
.size([width, height])
.on("tick", tick)
.start();
//draws the lines
function tick() {
link.attr("x1", function (d) { return d.source.x })
.attr("y1", function (d) { return d.source.y })
.attr("x2", function (d) { return d.target.x })
.attr("y2", function (d) { return d.target.y });
node.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });
}
function nodeByName(name) {
var groupNo;
switch (name.substring(0, 1)) {
case "A":
groupNo = 1;
break;
case "S":
groupNo = 2;
break;
default:
groupNo = 0;
}
return nodesByNames[name] || (nodesByNames[name] = { Name: name, group: groupNo });
}
});
};
我的数据:
App_Name,App_No,Server_Name,Server_No
App_01,A1,Server_01,S1
App_01,A1,Server_02,S2
App_01,A1,Server_03,S3
App_01,A1,Server_04,S4
App_02,A2,Server_03,S3
App_02,A2,Server_04,S4
App_02,A2,Server_05,S5
App_03,A3,Server_05,S5
App_03,A3,Server_06,S6
App_03,A3,Server_07,S7
我正在尝试将这两个示例(here和here)结合起来,以便在节点上具有拖动行为,同时能够进行语义缩放。我必须禁用缩放dblclick行为(请参阅代码),否则click
,drag
,fix
和un-fix
行为都可以正常运行,但是我在"cannot read property "on" of undefined"
库本身内发生d3
错误(chrome中的调试器显示它中断的行号(第1321行))。
我的代码是否正确?我是否在正确的位置(svg var
)应用缩放行为?我是否将转换应用于正确的组(在这种情况下是圈组?)
编辑:错误发生在d3.js库的第1321行。它说" g"一片空白。我出于某种原因可能只是有一个错误的d3库吗?
答案 0 :(得分:1)
我使用CSV转JSON转换器来转换数据,这样我就可以创建一个小提琴。所以这里:
在这个答案的帮助下:semantic zooming of force directed graph in d3
这个JSFiddle:http://jsfiddle.net/cSn6w/6/
我已经解决了这个问题。基本上你想拖动节点并保持它们就位,你已经解决了吗?你想放大但保持节点大小相同? (语义缩放)。
因此,当您进行缩放时,您需要更改节点的大小,但要获得正确的大小,您需要获得比例因子并获得您需要知道翻译因子的位置。所以创建像这样的变量:
var scaleFactor = 1;
var translation = [0,0];
这些将被覆盖。
现在缩放时你想要更新这些:
var zoom = d3.behavior.zoom()
.scaleExtent([0.1,10])
//allow 10 times zoom in or out
.on("zoom", zoomed);
function zoomed() {
// console.log("zoom", d3.event.translate, d3.event.scale);
scaleFactor = d3.event.scale;
translation = d3.event.translate;
tick(); //update positions
}
zoomed
函数更新比例并翻译我们之前声明的变量。然后调用tick来更新节点和链接的位置以及节点的大小。更新了刻度函数:
//draws the lines
function tick() {
link.attr("x1", function(d) {
return translation[0] + scaleFactor * d.source.x;
})
.attr("y1", function(d) {
return translation[1] + scaleFactor * d.source.y;
})
.attr("x2", function(d) {
return translation[0] + scaleFactor * d.target.x;
})
.attr("y2", function(d) {
return translation[1] + scaleFactor * d.target.y;
});
node.attr("cx", function(d) {
//console.log(translation[0] + scaleFactor*d.x)
return translation[0] + scaleFactor * d.x;
})
.attr("cy", function(d) {
return translation[1] + scaleFactor * d.y;
});
node.attr("transform", function(d) {
return "translate(" + (translation[0] + scaleFactor * d.x) + "," + (translation[1] + scaleFactor * d.y) + ")";
});
}
这里你必须要了解的是,当调用此函数时,它使用translate和scale变量来为节点提供正确的位置。
现在这样可以正常工作,但是由于你没有实现规模并在那里进行翻译,因此阻力不大。我已经改变了拖动功能:
var drag = force.drag()
.origin(function(d) {
return d;
})
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
function dragstarted(d) {
console.log('start')
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
}
function dragged(d) {
console.log('dragged')
d3.select(this).attr("cx", d.x = d3.event.x + translation[0]).attr("cy", d.y = d3.event.y + translation[1]);
}
function dragended(d) {
console.log('dragended')
d.fixed = true;
d3.select(this).classed("dragging", false);
}
注意在dragged
函数中我使用scale和translate来获得正确的位置。线d3.event.sourceEvent.stopPropagation();
也会停止闪烁,如果你拿出来就可以看出我的意思。
这是更新的小提琴:https://jsfiddle.net/reko91/rw0o9vxh/2/
这能解决您的问题吗?
PS
你没有工作,因为没有d [0]和d [1]的值。
答案 1 :(得分:-1)
这一行怎么样:
.call(
d3.behavior.zoom()
.x(X)
.y(Y)
.scaleExtent([1, 10])
.on("zoom", zoom)
)
.on("dblclick.zoom", null);
您可能想将dbliclick.zoom放在括号中。
否则,因为使用回调来加载csv,可能会吞下您的文件错误。
如果不是我链接的代码使用中间变量和debogguer工具来检查你是否有某个未定义的返回。 Builder模式很适合语法,但不适合调试。