To the esteemed readers. I'm reasonably new in javascript and I have come across this problem. I'm trying to implement a modified version of this force directed graph:
http://mbostock.github.com/d3/ex/force.html
The json data is generated on the fly from a php script. The idea is to color all lines connecting to one specific node ( defined in a php script) in one color and all the others in shades of gray. I'm attempting to do it by matching the source variable in the json file to the variable from the php script and changing color when that is true like this:
var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value);})
.style("stroke-opacity", function(d) { return d.value/10;})
.style("stroke", function(d) {
x = (tested == d.source) ? return '#1f77b4' : '#707070';// <-- Attempt to change the color of the link when this is true.
})
however this does not work. The script works fine but without the color change if I just do this
var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value);})
.style("stroke-opacity", function(d) { return d.value/10;})
.style("stroke", function(d) {
return '#707070';
})
I've been staring at this for days trying to figure out to get this done and I'm stuck. Any help would be greatly appreciated!!
Here is my complete script
<script type="text/javascript">
var width = 1200,
height = 1200;
var color = d3.scale.category20();
var tested=<?php echo $tested_source;?>; //<-- the variable from php
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("data.json", function(json) {
var force = d3.layout.force()
.charge(-130)
.linkDistance(function(d) { return 500-(50*d.value);})
.size([width, height]);
force
.nodes(json.nodes)
.links(json.links)
.start();
var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return Math.sqrt(d.value);})
.style("stroke-opacity", function(d) { return d.value/10;})
.style("stroke", function(d) {
x = (tested == d.source) ? return '#1f77b4' : '#707070'; //<-- Attempt to change the color of the link when this is true. But is is not working... :(
})
var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 12)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);
node.append("title")
.text(function(d) { return d.name; });
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
});
</script>
D3's force layout uses a physics based simulator for positioning visual elements. Forces can be set up between elements, for example: all elements can be configured to repel one another. elements can be attracted to center(s) of gravity.
It calculates the layout of the graph based solely on the information contained in the graph structure rather than relying on domain-specific knowledge. The nodes are represented by points that repel each other like magnets. Borders connect these points by simulating a spring force to attract adjacent nodes.
Typically, spring-like attractive forces based on Hooke's law are used to attract pairs of endpoints of the graph's edges towards each other, while simultaneously repulsive forces like those of electrically charged particles based on Coulomb's law are used to separate all pairs of nodes.
d.source
is an object, you can't use ==
to determine if tested
is a similar object. Have a look at this answer for more details on object equality.
If you want to test for a specific value of the d.source
object described below, which I assume you want, you need to specify it.
Here is the source object architecture : (I'm using the example you pointed so the data comes from the miserables.json
)
source: Object
group: 4
index: 75
name: "Brujon"
px: 865.6440689638284
py: 751.3426708796574
weight: 7
x: 865.9584580575608
y: 751.2658636251376
Now, here is the broken part in your code :
x = (tested == d.source) ? return '#1f77b4' : '#707070';// <-- Attempt to change the color of the link when this is true.
It doesn't work because the return is misplaced.
You're mixing ternary and return
statements but you don't put them in the right order :
return test ? value_if_true : value_if_false;
if you want to assign the value to x anyway, you can do
x = test ? value_if_true : value_if_false;
return x;
You should do something like this :
return (tested == d.source) ? '#1f77b4' : '#707070';// <-- Attempt to change the color of the link when this is true.
That's for the general syntax, but this won't work as is You need to pick one of the value for your test for example :
return (tested === d.source.name) ? '#1f77b4' : '#707070';
Also, if the variable from PHP is a string you should do
var tested="<?php echo $tested_source;?>"; //<-- the variable from php
and in most cases you should use json_encode
to map PHP variables into javascript ones.
As a final note, I would recommend using console
functions coupled with Firebug's console panel if you're using Firefox, or the Chrome Developer Tool's console panel if you're using a Chromium based browser. It would allow you to debug your code more easily.
var width = 960,
height = 500;
var color = d3.scale.category20();
var force = d3.layout.force().charge(-120).linkDistance(30).size([width, height]);
var svg = d3.select("#chart").append("svg").attr("width", width).attr("height", height);
var tested = 20;
d3.json("miserables.json", function (json) {
force.nodes(json.nodes).links(json.links).start();
var link = svg.selectAll("line.link")
.data(json.links)
.enter()
.append("line")
.attr("class", "link")
.style("stroke-width", function (d) {
return Math.sqrt(d.value);
}).style("stroke-opacity", function (d) {
return d.value / 10;
}).style("stroke", function (d) {
return (tested == d.source.index) ? '#ee3322' : '#707070'; //'#1f77b4'
});
var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter()
.append("circle")
.attr("class", "node")
.attr("r", 5)
.style("fill", function (d) {
return color(d.group);
}).call(force.drag);
node.append("title").text(function (d) {
return d.name;
});
force.on("tick", function () {
link.attr("x1", function (d) {
return d.source.x;
}).attr("y1", function (d) {
return d.source.y;
}).attr("x2", function (d) {
return d.target.x;
}).attr("y2", function (d) {
return d.target.y;
});
node.attr("cx", function (d) {
return d.x;
}).attr("cy", function (d) {
return d.y;
});
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With