簡體   English   中英

在d3.js中更改某一行的顏色

[英]Change a color of a certain line in d3.js

我已經在javascript中使用d3.js實現了一個網絡,我想根據收到的json將鏈接的顏色從灰色更改為紅色。 JSON顯示將要連接的源節點和目標節點。 節點架構的架構如下:

在此輸入圖像描述

現在,當收到JSON時,我解析數據,然后我將一條連接源節點和目標節點的新行添加到紅色,代碼如下:

       svg.selectAll()
          .data(data.links)
          .enter()
          .append("line")
          .attr("x1", function(d) { return nodes[source].x; })
          .attr("y1", function(d) { return nodes[source].y; })
          .attr("x2", function(d) { return nodes[target].x; })
          .attr("y2", function(d) { return nodes[target].y; })
          .attr("stroke","#b72b34")
          .attr("stroke-width", 2)

然后,在2秒后我使用相同的代碼再次將線的顏色更改為灰色。 還有另一種更簡單的方法嗎?

我現在的結果是: 在此輸入圖像描述

正如您所看到的,用戶可以看到過去添加的行,但這不是想要的圖像。 我只想更改現有鏈接的顏色(如架構1中所示)。

先感謝您。

我的代碼:

var nodes = [
 { x:   width/2, y: height/4, id: 0, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"},
 { x:   60, y: height-150, id: 1, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"},
 { x:   width-100, y: height-150, id: 2, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"},
 { x:   60, y: height-50, id: 3, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"},
 { x:   width-100, y: height-50, id: 4, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Inkjet-Printer-icon.png"}
  ];


  var links = [
  { source: 1, target: 2 },
  { source: 1, target: 3 },
  { source: 1, target: 4 },
  { source: 1, target: 0 },
  { source: 2, target: 3 },
  { source: 2, target: 1 },
  { source: 2, target: 4 },
  { source: 2, target: 0 },
  { source: 3, target: 4 },
  { source: 3, target: 1 },
  { source: 3, target: 2 },
  { source: 3, target: 0 },
  { source: 4, target: 1 },
  { source: 4, target: 2 },
  { source: 4, target: 3 },
  { source: 4, target: 0 },
  { source: 0, target: 1 },
  { source: 0, target: 2 },
  { source: 0, target: 3 },
  { source: 0, target: 4 },
  ];

  svg.selectAll()
     .data(links)
  .enter()
  .append("line")
   .attr("x1", function(d) { return nodes[d.source].x; })
   .attr("y1", function(d) { return nodes[d.source].y; })
   .attr("x2", function(d) { return nodes[d.target].x; })
   .attr("y2", function(d) { return nodes[d.target].y; })
   .attr("stroke-width", function (d) { return Math.sqrt(d.value); })
   .attr("stroke","#f6f6f6")
   svg.selectAll()
    .data(nodes)
    .enter()
    .append("image")
    .attr("x", function(d) { return d.x - 30/2; })  
    .attr("y", function(d) { return d.y - 30/2; })  
    .attr("width", 45)
    .attr("height", 45)
    .attr("xlink:href",function(d) { return d.url; })

    setInterval(function(test){
       var url = "http://..." 
       d3.json(url, function(error, data) {
       for (var i = 0; i < data.links.length; i++) {
         source = findNode(data.links[i].source);
         target = findNode(data.links[i].target);
            svg.selectAll()
              .data(data.links)
              .enter()
              .append("line")
              .attr("x1", function(d) { return nodes[source].x; })
              .attr("y1", function(d) { return nodes[source].y; })
              .attr("x2", function(d) { return nodes[target].x; })
              .attr("y2", function(d) { return nodes[target].y; })
              .attr("stroke","#b72b34")
              .attr("stroke-width", function (d) { return Math.sqrt(d.value); 
               })
          ;

  }
   });
   }, 5000);

您每次更新圖表時都會追加新行:

svg.selectAll()
   .data(data.links)
   .enter()
   .append("line")

svg.selectAll()是一個空選擇,與svg.selectAll(null)相同。 因此,在DOM中為數據陣列中的每個項目創建一個項目。 這會在一段時間后減慢速度。

我們可以選擇帶有svg.selectAll("circle")來更新(或退出/輸入舊/新行),但新數據數組將按其索引的順序分配給現有行,而不是數據對。 我們可以做的每一個元素的關鍵.selectAll().data() 作為第二個參數.data()但是這必須是一個字符串。

而不是使用密鑰,我建議使用我們可以給每行代表其源和目標的id(當最初附加行時):

 .attr("id", function(d) { return "link-"+d.source+"-"+d.target; })

然后,當我們處理json數據以更新圖形時,我們選擇合適的線條。 選擇后,我們應用該風格。 使用轉換延遲,我們可以確保在兩秒后完成轉換回正常:

newData.links.forEach(function(d) {
    d3.select("#link-"+d.source+"-"+d.target)
       .attr("stroke","red")
       .transition()
       .delay(1500)
       .duration(500)
       .attr("stroke","#f6f6f6")
})

這部分代碼適合您的超時功能:

 var width = 600; var height = 400; var svg = d3.select("body").append("svg") .attr("width",width) .attr("height",height); var nodes = [ { x: width/2, y: height/4, id: 0, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: 60, y: height-150, id: 1, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: width-100, y: height-150, id: 2, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: 60, y: height-50, id: 3, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: width-100, y: height-50, id: 4, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Inkjet-Printer-icon.png"} ]; var links = [ { source: 1, target: 2 }, { source: 1, target: 3 }, { source: 1, target: 4 }, { source: 1, target: 0 }, { source: 2, target: 3 }, { source: 2, target: 1 }, { source: 2, target: 4 }, { source: 2, target: 0 }, { source: 3, target: 4 }, { source: 3, target: 1 }, { source: 3, target: 2 }, { source: 3, target: 0 }, { source: 4, target: 1 }, { source: 4, target: 2 }, { source: 4, target: 3 }, { source: 4, target: 0 }, { source: 0, target: 1 }, { source: 0, target: 2 }, { source: 0, target: 3 }, { source: 0, target: 4 }, ]; svg.selectAll() .data(links) .enter() .append("line") .attr("x1", function(d) { return nodes[d.source].x; }) .attr("y1", function(d) { return nodes[d.source].y; }) .attr("x2", function(d) { return nodes[d.target].x; }) .attr("y2", function(d) { return nodes[d.target].y; }) .attr("stroke-width", function (d) { return Math.sqrt(d.value); }) .attr("id", function(d) { return "link-"+d.source+"-"+d.target; }) .attr("stroke","#f6f6f6") svg.selectAll() .data(nodes) .enter() .append("image") .attr("x", function(d) { return dx - 45/2; }) .attr("y", function(d) { return dy - 45/2; }) .attr("width", 45) .attr("height", 45) .attr("xlink:href",function(d) { return d.url; }) setInterval(function(){ // randomly links instead of calling external file: var data = links.filter(function(d) { if (Math.random() < 0.5) return d; }) data.forEach(function(d) { d3.select("#link-"+d.source+"-"+d.target) .attr("stroke","red") .transition() .delay(1500) .duration(500) .attr("stroke","#f6f6f6") }) }, 3000); // sped up for demonstration 
 <script src="https://d3js.org/d3.v3.min.js"></script> 

為了便於比較,這里是一個提供給.data()作為替代方法的密鑰。 為此,我們將目標和源轉換為字符串,就像我們為id做的那樣,但是將其作為.data()中的鍵應用。 這允許我們跳過每個循環。 這是一個更規范的d3方法

 var width = 600; var height = 400; var svg = d3.select("body").append("svg") .attr("width",width) .attr("height",height); var nodes = [ { x: width/2, y: height/4, id: 0, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: 60, y: height-150, id: 1, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: width-100, y: height-150, id: 2, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: 60, y: height-50, id: 3, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Computer-icon.png"}, { x: width-100, y: height-50, id: 4, url: "http://icons.iconarchive.com/icons/icons-land/vista-hardware-devices/128/Inkjet-Printer-icon.png"} ]; var links = [ { source: 1, target: 2 }, { source: 1, target: 3 }, { source: 1, target: 4 }, { source: 1, target: 0 }, { source: 2, target: 3 }, { source: 2, target: 1 }, { source: 2, target: 4 }, { source: 2, target: 0 }, { source: 3, target: 4 }, { source: 3, target: 1 }, { source: 3, target: 2 }, { source: 3, target: 0 }, { source: 4, target: 1 }, { source: 4, target: 2 }, { source: 4, target: 3 }, { source: 4, target: 0 }, { source: 0, target: 1 }, { source: 0, target: 2 }, { source: 0, target: 3 }, { source: 0, target: 4 }, ]; svg.selectAll() .data(links, function(d) { return d.source+"-"+d.target }) .enter() .append("line") .attr("x1", function(d) { return nodes[d.source].x; }) .attr("y1", function(d) { return nodes[d.source].y; }) .attr("x2", function(d) { return nodes[d.target].x; }) .attr("y2", function(d) { return nodes[d.target].y; }) .attr("stroke-width", function (d) { return Math.sqrt(d.value); }) .attr("stroke","#f6f6f6") svg.selectAll() .data(nodes) .enter() .append("image") .attr("x", function(d) { return dx - 45/2; }) .attr("y", function(d) { return dy - 45/2; }) .attr("width", 45) .attr("height", 45) .attr("xlink:href",function(d) { return d.url; }) setInterval(function(){ // randomly links instead of calling external file: var data = links.filter(function(d) { if (Math.random() < 0.5) return d; }) d3.selectAll("line") .data(data, function(d) { return d.source+"-"+d.target; }) .attr("stroke","red") .transition() .delay(1500) .duration(500) .attr("stroke","#f6f6f6") }, 3000); // sped up for demonstration 
 <script src="https://d3js.org/d3.v3.min.js"></script> 

您可以將行選擇緩存在變量中,以便在超時時重復使用它。 看看下面的代碼。 我還添加了一個可選的300ms過渡。

const redLine = svg.selectAll()
  .data(data.links)
  .enter()
  .append("line")
  .attr("x1", function(d) { return nodes[source].x; })
  .attr("y1", function(d) { return nodes[source].y; })
  .attr("x2", function(d) { return nodes[target].x; })
  .attr("y2", function(d) { return nodes[target].y; })
  .attr("stroke","#b72b34")
  .attr("stroke-width", 2)

// drop this code inside setTimeout() instead of the whole block of code from 
// above that you repeat
redLine
  .transition(300)
  .attr("stroke","grey")
  .attr("stroke-width", 1)

暫無
暫無

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

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