Reputation: 923
I am using a D3 api to show some nodes in an order ,the nodes are coming to the page in same color.When i hover on a node then its changing into some other color. but I want a fixed color for a node (different from others) in the time of loading. I am using this api.. please help me...
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node circle {
stroke: white;
stroke-width: 1.5px;
opacity: 1.0;
}
line {
stroke: black;
stroke-width: 1.5px;
stroke-opacity: 1.0;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
data = {
nodes : [ {
size : 10
}, {
size : 5
}, {
size : 2
}, {
size : 3
} ],
links : [ {
source : 0,
target : 1
}, {
source : 0,
target : 2
} ]
}
var mouseOverFunction = function(d,i) {
var circle = d3.select(this);
//$ fill = d3.scale.category20();
node.transition(500).style("opacity", function(o) {
return isConnected(o, d) ? 1.0 : 0.2;
}).style("fill", function(o) {
if (isConnectedAsTarget(o, d) && isConnectedAsSource(o, d)) {
fillcolor = 'green';
} else if (isConnectedAsSource(o, d)) {
fillcolor = 'red';
} else if (isConnectedAsTarget(o, d)) {
fillcolor = 'blue';
} else if (isEqual(o, d)) {
fillcolor = "hotpink";
} else if(isNot(o,d)){
//here the output will shown when no mouse event is occured
}
return fillcolor;
});
link
.transition(500)
.style("stroke-opacity", function(o) {
return o.source === d || o.target === d ? 1 : 0.2;
})
.transition(500)
.attr(
"marker-end",
function(o) {
return o.source === d || o.target === d ? "url(#arrowhead)"
: "url()";
});
circle.transition(500).attr("r", function() {
return 1.4 * node_radius(d)
});
}
var mouseOutFunction = function() {
var circle = d3.select(this);
node.transition(500);
link.transition(500);
circle.transition(500).attr("r", node_radius);
}
function isConnected(a, b) {
return isConnectedAsTarget(a, b) || isConnectedAsSource(a, b)
|| a.index == b.index;
}
function isConnectedAsSource(a, b) {
return linkedByIndex[a.index + "," + b.index];
}
function isConnectedAsTarget(a, b) {
return linkedByIndex[b.index + "," + a.index];
}
function isEqual(a, b) {
return a.index == b.index;
}
//here i have trying to make root node a separate color and the child nodes two separate colors
function isNot(a,b){
return d3.scale.category20()(i);
}
function tick() {
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("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
function node_radius(d) {
return Math.pow(40.0 * d.size, 1 / 3);
}
var width = 1000;
var height = 500;
var nodes = data.nodes
var links = data.links
var force = d3.layout.force().nodes(nodes).links(links).charge(-3000)
.friction(0.6).gravity(0.6).size([ width, height ]).start();
var linkedByIndex = {};
links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = true;
});
var svg = d3.select("body").append("svg").attr("width", width).attr(
"height", height);
var link = svg.selectAll("line")
.data(links)
.enter()
.append("line");
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.style("fill", function (d) {
return '#1f77b4';
})
.attr("class", "node")
.attr("cx",function(d) {
return d.x;
})
.attr("cy",function(d) {
return d.y;
})
//.attr("fill",function(d){return color(d.range);})
.call(force.drag);
node.append("circle")
.attr("r", node_radius)
.on("mouseover", mouseOverFunction)
.on("mouseout", mouseOutFunction);
svg.append("marker")
.attr("id", "arrowhead")
.attr("refX", 6 + 7) // Controls the shift of the arrow head along the path
.attr("refY", 2)
.attr("markerWidth", 6)
.attr("markerHeight", 4)
.attr("orient", "auto")
.append("path")
.attr("d", "M 0,0 V 4 L6,2 Z");
link.attr("marker-end", "url()");
force.on("tick", tick);
</script>
</body>
Upvotes: 2
Views: 1025
Reputation: 15325
I think you are nearly there with your code. On mouseover you should modify the 'fill' css property of your node.
To do so, in d3 you must use:
node.append("circle")
.attr("r", node_radius)
.on("mouseover",mouseOverFunction)
as you did. In moueOverFunction you have two choices to get properties for a given node:
1) Get the color from a property of the node:
function mouseoverFunction(node) {
if(node.size<10) {
return 'blue'
} else {
return 'red'
}
}
2) Get the color from the position of the node in the data array:
function mouseoverFunction(node,index) {
if(index<2) {
// Will color the two first nodes blue
return 'blue'
} else {
// All others will be red
return 'red'
}
}
In the end for your specific problem I would do:
function mouseoverFunction(node,index) {
if(index<3) {
return ['red','green','blue'][index]
} else {
// index should be less than 3
return 'black'
}
}
Upvotes: 1