I am looking at the Bubble Chart by Mike Bostock: http://bl.ocks.org/mbostock/4063530 that uses circle packing. I would like to however, be able to color the circles by the name of the containing class.
I am trying it in JSBin here: http://jsbin.com/qoveguvopu/edit?css,js,output
My fault is here:
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) {return color(d.data.name);});
Thanks!
Kind of like this:
You can get the data bound to the parent...
d.parent.data.name
... and color the circles according to it, first checking if a parent exists:
node.append("circle")
.attr("r", function(d) {
return d.r;
})
.style("fill", function(d) {
if (d.parent) {
return color(d.parent.data.name)
};
});
Here is your updated Bin: http://jsbin.com/ruyegidopo/1/edit
Related
I'm trying to get the fill of each bubble to be set by the "fill" column in my CSV chart. Here is the link to the plunker: https://plnkr.co/edit/XIvmdQXLWFF8Nhz0VTps?p=preview
I believe it should be set at the style function below. I'm assuming my return color is not set correctly.
node.append("circle")
.attr("id", function(d) { return d.id; })
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.data.fill); });
color points to a function that returns a different predefined color on each call. In order to change the color of each bubble, you'll have to return color of the fill for that particular bubble.
If you would change the style to .style("fill", function(d) { console.log(d.data.fill); return color(d.data.fill); }), the strings of colors will be printed, so that's fine. All we have to do is to change the code to return the actual color. This can be done by changing it to .style("fill", function(d) { return d3.rgb(d.data.fill); }), or .style("fill", function(d) { return d.data.fill; }) in short.
In the following d3.js code:
svg.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("transform", "translate(10,0)")
.attr("class", "bar")
.attr("x", function(d) { return x(d.thread_id); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(+d.traffic); })
.attr("height", function(d) { return height - y(+d.traffic); })
.on('mouseover', tip.show) // First time call to show a tooltip
.on('mouseover', justChecking) // Second time to call a Function
.on('mouseout', tip.hide);
When I execute this code, only the second function output is shown but the tooltip disappears.
I want to call both of them on mouseover, i.e., call the function as well as show the tooltip. Any ideas are appreciated?
Any event handler you attach overwrites previously attached event handlers. You can however call both of your functions in the same handler:
.on('mouseover', function(d, i) {
tip.show(d, i);
justChecking(d, i);
})
While I've seen this question asked a few times, I'm having a bit trouble implementing. What I'd like to do is have the label attribute centered within each circle (as mentioned here). I believe I'd be adding the text attribute to:
canvas.selectAll('circles')
.data(nodes)
.enter()
.append('svg:circle')
.attr('cx', function (d) {
return d.x;
})
.attr('cy', function (d) {
return d.y;
})
.attr('r', function (d) {
return d.r;
})
.attr('fill', function (d) {
return d.color;
});
But am confused on why the instructions they gave in the previous example I linked to doesn't work with the setup I currently have. I believe it's the pack option that could be throwing me off (about the difference between the two), but any further examples would be a huge help. Thanks!
Update
Thanks for the answers/suggestions, I updated the Codepen with my progress (as I needed two lines of data; should have clarified) which seems to be working well. Now this is packing into a circle - at the end of the day, I'd love for this to be packed in the actual #canvas width/height (which is a rectangle). I saw this treemap example - would that be what I'm going for here?
Demo of what I have so far
Perhaps the confusion is that you can't add labels to the circle selection (because in SVG, a circle element can't contain a text element). You need to either make a g element that contains both circle and text, or a separate selection for the text, e.g.:
canvas.selectAll('text')
.data(nodes)
.enter()
.append('svg:text')
.attr('x', function (d) {
return d.x;
})
.attr('y', function (d) {
return d.y;
})
// sets the horizontal alignment to the middle
.attr('text-anchor', "middle")
// sets the vertical alignment to the middle of the line
.attr('dy', '0.35em')
.text(function(d) {
return d.label;
});
See the updated demo: http://codepen.io/anon/pen/djebv
I'm banging my head here. I want to display tooltips for the leaf nodes in a structure such as Zoomable Pack Layout. The leaf nodes are the brown ones. If I used the standard code for tooltips:
vis.selectAll("circle")
.data(nodes)
.enter()
.append("svg:circle")
.attr("class", function(d) {
return d.children ? "parent" : "child";
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", function(d) {
return d.r;
})
.on("click", function(d) {
zoom(node == d ? root : d);
})
.append("svg:title")
.text("test"); \\ Browser uses this for tooltips
I get tooltips on the primary circles but not on the leaf nodes. I tried:
.append("svg:title")
.text(function(d) {
if(d.size){return 'test';}
});
...hoping that by returning something only when a varaible contained by leaf nodes is present may prevent the parent nodes from showing a tooltip but I'm afraid all it did was allow a hidden tooltip taht silently prevents anything from displaying.
Any thoughts? I figure I either need to stack the svg:circles so that the leaf nodes are in front of the others or attach svg:titles only to the leaf nodes but I'm not sure how to do that.
Here is a fiddle of the tooltips:
Fiddle
The problem is in fact not the code, but the CSS that prevents the leaf node circles from receiving pointer events. Simply remove
circle.child {
pointer-events: none;
}
and it works fine. Complete example here.
I'm working on building a molecule creator in D3 using the original example created by Mike Bostock: http://bl.ocks.org/mbostock/3037015
I'm using a force layout just like in the example. My problem is when I add a new Node/atom dynamically, it doesn't move with the rest of the graph. I've read other questions and implemented everything that is suggested and have made sure that I'm following the proper update/join procedure that D3 requires and yet still the added carbon refuses to move with the rest of the graph.
Here is my update/create function:
function buildMolecule () {
// Update link data
link = link.data(links);
// Create new links
link.enter().append("g")
.attr("class", "link")
.each(function(d) {
d3.select(this)
.insert("line", ".node")
.style("stroke-width", function(d) { return (d.bond * 2 - 1) * 2 + "px"; });
d3.select(this)
.filter(function(d) { return d.bond > 1; }).append("line")
.attr("class", "separator");
d3.select(this)
.on("click", bondClicked);
});
// Delete removed links
link.exit().remove();
// Update node data
node = node.data(nodes);
// Create new nodes
node.enter().append("g")
.attr("class", "node")
.on("click", atomClicked)
.each(function(d) {
console.log('d:', d);
// Add node circle
d3.select(this)
.append("circle")
.attr("r", function(d) { return radius(d.size); })
.style("fill", function(d) { return color(d.atom); });
// Add atom symbol
d3.select(this)
.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.atom; });
d3.select(this).call(force.drag);
});
// Delete removed nodes
node.exit().remove();
force.start();
}
JsFiddle: http://jsfiddle.net/2dPMF/1/
Any help would be greatly appreciated!
You're modifying the data structures of the nodes and links beyond adding and deleting nodes, which messes up the force layout. I'm talking about these lines in particular.
function bigBang () {
links = links.concat(linksList);
nodes = nodes.concat(nodesList);
buildMolecule();
}
The first two lines in that function are what I'm talking about. Working jsfiddle here.