我正在尝试通过单击强制定向网络中的节点来更新条形图的内容。目前,我正在尝试在主面板上使用“mousemove”事件,并使用“point”事件更新变量activeNode,然后通知我希望访问哪一行。我遇到的问题是,主面板中的点事件没有更新activeNode,并且它总是设置为默认值。试着到处寻找解决方案,但我想我错过了一些更基本的概念。
这是代码......
var w = document.body.clientWidth,
h = document.body.clientHeight,
colors = pv.Colors.category19(),
activeNode = 0;
var vis = new pv.Panel()
.width(w)
.height(h)
.fillStyle("white")
.event("mousemove", pv.Behavior.point(Infinity));
var force = vis.add(pv.Layout.Force)
.width(w-200)
.nodes(miserables.nodes)
.links(miserables.links);
force.link.add(pv.Line);
force.node.add(pv.Dot)
.def("o",-1)
.size(function(d) (d.linkDegree + 10) * Math.pow(this.scale, -1.5))
.fillStyle(function(d) d.fix ? "brown" : colors(d.group))
.strokeStyle(function() this.fillStyle().darker())
.lineWidth(1)
.title(function(d) this.index)
.event("mousedown", pv.Behavior.drag())
.event("drag", force)
.event("point", function() {activeNode = this.index; return vis;});
vis.add(pv.Label).top(20).left(w/2).text("activeNode = " + activeNode);
vis.add(pv.Bar)
.data(topw[activeNode].splice(0))
.top(function(d) this.index * 30)
.left(w-80)
.width(15)
.height(20)
.anchor("left").add(pv.Label)
.textAlign("right")
.text(function(d) d[0]);
vis.render();
答案 0 :(得分:2)
这里有几个问题,但基本的问题是概念性的 - 当你在可视化中声明标记的属性时,你可以使用一个值,如:
.width(10)
或功能,如:
.width(function() { return 10; })
不同之处在于,每次render()
vis(或vis的相关部分)时,都会重新评估第二个版本。例如,你在哪里:
vis.add(pv.Label).top(20).left(w/2).text("activeNode = " + activeNode);
这只会在第一次呈现vis时进行评估。相反,你需要一个功能:
// assign the label to a variable, so we can refer to it later
// this is easiest if we define the label and bar first
var nodeLabel = vis.add(pv.Label)
.top(20)
.left(w/2)
.textAlign("right") // easier for my bar layout
// note that this has to be a function, so that it will be
// re-evaluated on re-render
.text(function() {
return "activeNode = " + (activeNode ? activeNode.nodeName : 'None')
});
因此,您更正的代码可能如下所示(我更改了条形图,因为我无法访问您引用的topw
数据):
var w = document.body.clientWidth,
h = document.body.clientHeight,
colors = pv.Colors.category19(),
activeNode = null;
var vis = new pv.Panel()
.width(w)
.height(h)
.fillStyle("white")
.event("mousemove", pv.Behavior.point(Infinity));
// assign the label to a variable, so we can refer to it later
// this is easiest if we define the label and bar first
var nodeLabel = vis.add(pv.Label)
.top(20)
.left(w/2)
.textAlign("right") // easier for my bar layout
// note that this has to be a function, so that it will be
// re-evaluated on re-render
.text(function() {
return "activeNode = " + (activeNode ? activeNode.nodeName : 'None')
});
// again, assign the bar to a variable
// I think I'm missing some data for your example, so
// I made a single bar to show node degree
// (only one data point, so no .data() needed)
var nodeBar = vis.add(pv.Bar)
.top(0)
.left(w/2)
.height(20)
.width(function() {
// make a scale based on all nodes
var scale = pv.Scale.linear(
// get the max link degree to be the upper limit of the scale
0, pv.max(miserables.nodes, function(d) { return d.linkDegree; })
).range(0, 200);
// return a value based on the active node
return activeNode ? scale(activeNode.linkDegree) : 0;
});
var force = vis.add(pv.Layout.Force)
.width(w-200)
.nodes(miserables.nodes)
.links(miserables.links);
force.link.add(pv.Line);
force.node.add(pv.Dot)
.def("o",-1)
.size(function(d) (d.linkDegree + 10) * Math.pow(this.scale, -1.5))
.fillStyle(function(d) d.fix ? "brown" : colors(d.group))
.strokeStyle(function() this.fillStyle().darker())
.lineWidth(1)
.title(function(d) this.index)
.event("mousedown", pv.Behavior.drag())
.event("drag", force)
.event("point", function(d) {
// set the global variable to point to the current node
activeNode = d;
// re-render the label
nodeLabel.render();
// re-render the bar
nodeBar.render();
});
vis.render();