Json 到.data(),因此数据由id匹配。页面元素(您使用的.data()的)与强制布局的操作不同(.nodes()和.links())。如果添加新节点和链接或删除现有节点和链接,也需要更新这些节点和链接。在那里,您需要手动将节点/链接与现有节点/链接进行匹配
到.data(),因此数据由id匹配。页面元素(您使用的Json 到.data(),因此数据由id匹配。页面元素(您使用的.data()的)与强制布局的操作不同(.nodes()和.links())。如果添加新节点和链接或删除现有节点和链接,也需要更新这些节点和链接。在那里,您需要手动将节点/链接与现有节点/链接进行匹配,json,d3.js,data-visualization,force-layout,Json,D3.js,Data Visualization,Force Layout,到.data(),因此数据由id匹配。页面元素(您使用的.data()的)与强制布局的操作不同(.nodes()和.links())。如果添加新节点和链接或删除现有节点和链接,也需要更新这些节点和链接。在那里,您需要手动将节点/链接与现有节点/链接进行匹配。 $("#customer").change(function(){ // this is the dropdown menu $("#customer option:selected").each(function ()
.data()
的)与强制布局的操作不同(.nodes()
和.links()
)。如果添加新节点和链接或删除现有节点和链接,也需要更新这些节点和链接。在那里,您需要手动将节点/链接与现有节点/链接进行匹配。
$("#customer").change(function(){ // this is the dropdown menu
$("#customer option:selected").each(function () {
var line = d3.selectAll("line").remove(); // remove all links on screen
var g = d3.selectAll("g").remove(); // remove all nodes on screen
dataFile = this.innerHTML; // changes variable used in d3.json
change(); // calls function wrapper that contains d3.json
});
function change(){
d3.json(dataFile, function(fileData){
rtm = new Object(); // initialize dictionary object
dates = []; // initialize dates[] array to contain all dates in data
var node = {}; // node object
// traverse through data contained in file
for(var i = 0; i < fileData.nodes.length; i++){
node = fileData.nodes[i]; // assign current node to node object
node.date = new Date(node.date);
rtm[node.id] = node; // add node object to dictionary object
// check if date exists in dateArray
if(findDate(node.date, dates)){
dates.push(node.date); // add dates that don't exist
}
}
getNodes(fileData.nodes[0].date); // finds the nodes to be visualized and updates the array passed to force.nodes()
getLinks(fileData.nodes[0].date); // finds the nodes to be visualized and updates the array passed to force.links()
start(); // initiates visualization after d3.json() finishes
});
}
// function controls visualization. Uses d3.js framework to control visualization
// must be called from within d3.json for first initialization or nothing will render
function start(){
// stop force functionality to allow for removal and adding of new objects
force.stop();
// remove all elements inside visualization
var line = d3.selectAll("line").remove(); // remove all links on screen
var g = d3.selectAll("g").remove(); // remove all nodes on screen
// create any links needed, dependent on links contained links[] array
// selects links already created or adds new links.
link = svg.selectAll("line.link")
.data(force.links(), function(d){ return d.id;}) // 2nd parameter can be added to use as a comaparison for pairing existing links with identical same data
link.enter().append("line") // new data will be bound to a new line. 2nd parameter in .data() allows for element reuse
// instead of creation, otherwise data and line elements are matched on index. If those
// two don't match then a new element is created.
.attr("class", "link") // assigns .link class to link element to allow for css styling
//.style("stroke-opacity", .5)
.style("stroke-width", 8)
.style("stroke", function(d){
return d.target.id > 7 ? (d.target.fraud ? "Red" : "#35586C") : "Grey";
});
link.exit().remove(); // removes any links removed from links[] array
// create any nodes needed, dependent on data contained in .data()
// selects nodes already created or adds new nodes. matches nodes to data
node = svg.selectAll(".node")
.data(force.nodes(), function(d){ return d.id;}) // 2nd parameter can be added to use as a comaparison for pairing existing node with identical same data
node.enter().append("g") // new data will be bound to a new node. 2nd parameter in .data() allows for element reuse
// instead of creation, otherwise data and node elements are matched on index. If those
// two don't match, a new element is created.
.attr("class", "node") // assigns .node class to node element to allow for css styling
.call(force.drag); // allows for nodes to be dragged and moved. x,y coordinates will adjust to movement
//.transition().duration(10000).delay(10000); // transitions any new nodes into the visualization
node.exit().remove(); // removes any nodes removed from nodes[] array
node.append("image")
.attr("xlink:href", function(d){
// add path for image of each node
var path = "images/";
if(!d.fraud){ // check if fraudulent node
if(d.name == "Record"){
path += "record-G.gif";
return path;
}
if(d.id <= 7){
path += "Record/";
}else {
path += "Linked/";
}
if(d.name == "SSN"){
path += "SSN.png";
}else if(d.name == "Name"){
path += "Name.png";
}else if(d.name == "Address"){
path += "Address.png";
}else if(d.name == "Phone"){
path += "Phone.png";
}else if(d.name == "DOB"){
path += "DOB.png";
}else if(d.name == "Email"){
path += "Email.png";
}else if(d.name == "Record"){
path += "record-G.gif";
}else if(d.name == "App"){
path += "App.png";
}else {
path += "nan.gif";
}
}else {
path += "FraudApp.png"
}
return path;
})
.attr("class", "image")
.attr("x", function(d){ return d.name == "Record" ? -30 : -20})
.attr("y", function(d){ return d.name == "Record" ? -30 : -20})
.attr("height", function(d){ return d.name == "Record" ? 60 : 40})
.attr("width", function(d){ return d.name == "Record" ? 60 : 40});
force.start(); // restart force functionality
}