簡體   English   中英

如何通過javascript(d3)更改節點CSS的樣式

[英]How do i change the styling of a nodes CSS through javascript(d3)

這是我的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。

抱歉,我的論文長篇大論,我只想為您提供盡可能多的細節,使每個人都更容易。

看來您做得差不多。 問題是您的代碼假定未在節點上調用.classed("selectedNode", true)導致該節點.selectedNode應用.selectedNode類。 但是實際上(您將可以在瀏覽器開發人員工具的“元素”面板中看到此內容),如果取消選擇節點,則該節點將具有.unselectedNode但也具有.selectedNode ,因為不會刪除.selectedNode類。 而且,任何后續的選擇/取消選擇操作都不會再修改內容,因為該節點已經具有兩個類。

因此,您需要在每次發生交互時通過調用以下方法刪除不適用的類:

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

最后一件事:在兩個位置( selectedNodesArrayd.selectedNode )維護有關selectedness的信息d.selectedNode 如果您可以選擇並使用這兩種方式中的一種來表示選定狀態,則前進的時間會更容易。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM