【问题标题】:How do i change the styling of a nodes CSS through javascript(d3)如何通过 javascript(d3) 更改节点 CSS 的样式
【发布时间】:2014-11-20 15:19:50
【问题描述】:

这是我的css

.node.selectedNode {
    width:50px;
    height:50px;
    stroke-width: 3px;
    stroke: #f00;
}

.node.unselectedNode {
    width:35px;
    height:35px;
    stroke-width: 3px;
    stroke: #000;
}

我想点击一个节点使其被选中(给它选定的属性),再次单击并使其未选中。 这是一段代码,我在其中检查节点的 id 是否在数组中,如果不是,则添加它,使我能够轻松打印出选定的节点。

if(selectedNodesArray.indexOf(d.coreId)==-1){
       selectedNodesArray.push(d.coreId);
       d.selectedNode = true; //change style
       d.unselectedNode = false;
       d3.select(this).classed("selectedNode", true);
       console.log("clicked");
}else{
        selectedNodesArray.pop(d.coreId);
        d.unselectedNode = true;
        d.selectedNode = false;
        d3.select(this).classed("unselectedNode", true);
        console.log("pulled"); 
}

您可能会注意到我尝试更改样式。现在这工作了两次;当我选择它和取消选择它时。之后它不再工作了。有什么想法吗?

另外,我创建了一个按钮,以便清除所有突出显示的节点。就像我在这里一样,当我单击节点时,它会将其属性更改为固定

function dragstart(d) {
  d.fixed = true;
  d3.select(this).classed("fixed", true);

我想在单击按钮时执行此操作,因此它会更改节点的 css 属性。我不知道如何挑选出所有节点并赋予它们所有相同的 css 属性,而不是通过 D3 来完成并以这种方式更改 .style。

抱歉,这篇文章冗长,我只想为您提供尽可能多的细节,以便大家更轻松。

【问题讨论】:

    标签: javascript html css node.js d3.js


    【解决方案1】:

    看起来你做的几乎是正确的。问题是您的代码假定不在节点上调用 .classed("selectedNode", true) 会导致它没有应用 .selectedNode 类。但实际上(您将能够在浏览器的开发人员工具的元素面板中看到这一点),如果您取消选择一个节点,它将有.unselectedNode 和.selectedNode,因为没有任何东西会删除@987654325 @ 班级。而且,任何后续的选择/取消选择都不再修改内容,因为节点已经拥有这两个类。

    所以你需要在每次交互发生时删除不适用的类,通过调用

    d3.select(this).classed("selectedNode", false);
    

    和

    d3.select(this).classed("unselectedNode", false);
    

    在适当的地方。这样就可以了。

    但现在你有机会重构一些东西。

    首先,我的建议是完全忘记unselectedNode 类,只使用.node 类来设置取消选中状态的样式。这样你就只有一个 selectedNode 类,它是默认样式的修饰符,这样你的代码会更简单。

    最后,我猜你正在使用强制布局,所以你已经有一个 tick() 函数或类似的函数,它每秒更新所有节点很多次。因此,将所有内容放在一起,您可以在该方法中执行所有操作:

    var selectedNodesArray = [];
    
    function tick() {
      var nodes = d3.selectAll('.node').data(force.nodes);
    
      // ENTER
      nodes.enter()
        .append('circle')// or 'rect' or whatever
        .attr('class', 'node')
        .on('click', function(d) {
          // here you set the selected-ness, but not the visual representation
    
          d.selectedNode = !d.selectedNode; // flip the selected-ness from true->false or vice versa
          console.log(d.selectedNode ? "clicked" : "pulled");
    
          // here you manage the array
          if(!d.selectedNode) {
            // note that pop() is actually unsafe here, bc it
            // removes the last-selected node, but what if you
            // deselect something from 2 clicks ago?
            selectedNodesArray.pop();
          }
          else {
            // Here I recommend pushing d, instead of its d.coreId, because
            // then you can use this array to get the actual datums of the 
            // selectedNodes, rather than just their id
            selectedNodesArray.push(d);
          }
        })
        ...// do whatever else you need to do to the entering nodes
    
      // UPDATE
      nodes
        // Here you take care of the representation of selected-ness
        .classed('selectedNode', function(d) {
          return d.selectedNode
          // or: return selectedNodesArray.indexOf(d)==-1
        })
        // do whatever else you need to do to the updating nodes (position, etc)
    }
    

    关于你的第二个问题:我不确定你到底在问什么,但我认为如果你认为你的 tick() 方法是基于仅数据模型或状态更新表示的东西(例如selectedNodesArray 或d.selectedNode),那么任何交互都可以修改该状态并让tick() 使表示达到速度。例如,这是取消选择所有内容的批量方法:

    // loop through the array and set selected to `false`
    selectedNodesArray.forEach(function(d) {
      d.selectedNode = false;
    })
    selectedNodesArray = [];// clear the array
    tick();// To update the visuals
    

    最后一件事:您在 2 个地方(selectedNodesArray 和 d.selectedNode)维护有关选择的信息有点奇怪。如果您可以选择并使用这两种方式中的一种来表示选择性,那么您将更容易前进。

    【讨论】:

    • 救命稻草。感谢深入回答的努力。它现在完美运行。就像你说的那样,我所缺少的只是一行 ''d3.select(this).classed("selectedNode", false); ''总是一件小事。再次感谢:)
    猜你喜欢
    • 1970-01-01
    • 2018-04-17
    • 2022-01-21
    • 2011-09-18
    • 1970-01-01
    • 2011-05-27
    • 2016-01-19
    相关资源
    最近更新 更多