[英]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.