如何通过单击力定向网络中的节点来更新外部条形图

发布于 2024-11-03 10:58:42 字数 1382 浏览 1 评论 0原文

我试图通过单击力导向网络中的节点来更新条形图的内容。目前,我正在尝试将主面板上的“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();

I'm trying to update the contents of a bar chart by clicking on a node in a force directed network. Currently, I'm trying to use the "mousemove" event on the main panel with a "point" event that updates the variable activeNode which then informs which row I hope to access. I'm having trouble with the fact that my point event from the main panel doesn't update activeNode and its always set to its default value. Tried looking everywhere for a fix with this, but I think I'm missing some more fundamental concept.

Here is the code...

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();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

征﹌骨岁月お 2024-11-10 10:58:42

这里有几个问题,但基本的问题是概念性的 - 当您在可视化中声明标记上的属性时,您可以使用值,例如:

.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();

There are a couple of issues here, but the basic one is conceptual - when you're declaring the properties on marks in your visualization, you can either use a value, like:

.width(10)

or a function, like:

.width(function() { return 10; })

The difference is that the second version will be re-evaluated each time you render() the vis (or the relevant part of the vis). So for example, where you have:

vis.add(pv.Label).top(20).left(w/2).text("activeNode = " + activeNode);

this will only be evaluated the very first time the vis is rendered. Instead, you need a function:

// 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')
    });

So your corrected code might look like this (I changed the bar chart a bit, since I don't have access to the topw data you reference):

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文