I am trying to set color of text node in nvd3 but it is not working because parent g node overrides it somehow. Here is what I am trying to do:
g.append("text")
.attr("x", center[0])
.attr("y", center[1])
.attr("dy", ".35em")
.style("fill", "white")
.text(key);
So, the .style("fill", "white") is not working.
Here is how the DOM looks like:
Text node is appended (as a child of the last g, I am just not showing it since it is way below), I see it with the right fill property, but the color of the appended text is still rgb(44, 123, 182).
Any suggestions would be greatly appreciated.
I decided to just append the text nodes to the parent of the nv-group element that was determining the color and it started to work. If anyone knows how to actually override the color, please, share the answer.
Related
I'm building a simple bar chart using d3.js and it works fine.
However, when I try to display texts on each bar, nothing happens. The console doesn't return any error so I can't understand the problem.
My code is available here, I tried to display simple text like "Hello" but still nothing shows up.
Problem:
Appending texts to a rect element in SVG.
Solution:
Append the texts to the SVG or to a group.
Instructions:
You are appending your texts to the rectangles. Nothing will show up as an error in the console because there is no error to show, but the texts won't appear.
You have to create a variable for the texts:
var texts = svg.selectAll(".mytexts")
.data(data)
.enter()
.append("text");
And then setting the attributes:
texts.attr("class", "value")
.attr("x", function(d) { return widthScale(d.vacant); })
.attr("y", heightScale.rangeBand() / 2)
.attr("dx", -3)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function(d) { return format(d.vacant); });
Don't forget to change the CSS accordingly.
I have a D3 chart with an axis that I want to style via the original calls to create it. However it only seems to work on the first call. I'll show you what I mean:
When I create the axis via
svg.select('g.y.axis').call(yaxis)
.selectAll("path")
.attr("fill","none")
.attr("stroke", "#000")
.selectAll("line")
.attr("fill","none")
.attr("stroke", "#000");
Only the path is styled correctly. You can check out my jsfiddle to see what I mean. I know this may be slower than just having CSS styles but I need it to be styled in the original call for what I'm working on. Thanks in advance!
It's because d3.selectAll("foo").selectAll("bar") will try to find <bar>s that are inner elements to founded <foo>s. And in your case svg finds no <line>s in <path>s.
Just call separately:
svg.selectAll("path")...
svg.selectAll("line")...
UPD
To find path/line in .y.axis:
svg.select(".y.axis").selectAll("path")
or
svg.selectAll(".y.axis path")
In the process of learning D3.js.
Is it possible using a force layout to place a circle within another circle shape as per the picture. I am hoping to transition between a single circle per node to a display showing two circles per node. The size of the effective donut is used to illustrate another variable in the data.
Is this possible?
You don't even need to use anything other than a basic svg circle, as you find in most examples. Just bind the data to it, apply a stroke, and set the stroke-width attr to your other variable. Or r - otherVar, I'm sure you can figure that part out.
If this doesn't satisfy, build your own shape. The 'g' svg element is a container element, and lets you build whatever you like. Add two circles to a g, fill them how you like. Make sure to add them in the right order, since svg has no concept of 'on top', things just get painted in the order that you add them.
edit: okay, quick demo so you can learn some syntax. I didn't add any comments but hopefully the code is very verbose and straightforward. Find it here.
d3/svg is something that you have to just bash your head against for a while. I highly recommend spending some time creating a sandbox environment where you can quickly test new things, save, refresh browser to see results. Minimizing that turnaround time is key.
Thanks to roippi I was able to create a group containing two circle shapes.
var nodeCircles = svg.selectAll("g")
.data(nodes);
// Outer circle
var outer = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius_plus; })
.style("fill", function(d) { return d.color_plus; })
.style("opacity", 0);
// Inner circle
var inner = nodeCircles
.enter()
.append("circle")
.attr("class", "node_circle")
.attr("r", function(d) { return d.radius; })
.style("fill", function(d) { return d.color; })
.style("stroke", function(d) { return d3.rgb(d.color).darker(2); })
.on("mouseover", mouseOver)
.on("mouseout", mouseOut)
.call(force.drag);
Outer circle visibility is toggled via a button.
As mentioned, I use a desktop based IDE to run/test visualisation languages. Currently the IDE supports studies written in D3.js, Raphael, Processin.js, Paper.js and Dygraphs. Picture below...
I have a dataset of 100 numbers, and within an SVG I create a bunch of text objects to display those numbers using the code below:
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
console.log(output_format(d));
return output_format(d);
This works perfectly. However, if I try to create a title later on (outside of my d3.csv brackets) with this code:
svg.append("text")
.text("Actual Labels")
.attr("x", w/1.92)
.attr("y", top_gap/1.5)
.attr("class", "title");
Then the first datapoint gets erased, and does not even display in console.log(output_format(d));. What is happening here and how do I fix this?
What happens is that your single text element is appended first because the other code has to wait for the AJAX request. So when you're appending the remainder of your text elements, one is already there. This existing text element is selected by selectAll("text") and then matched with the data in dataset. By default, d3 matches data based on the index -- the first element in the array matches the first element that is already there and is therefore not in the .enter() selection which you operate on.
The easiest way to fix this is to give the text labels that you append dynamically a different class and select based on that. That is, your code for appending the dynamic labels would look like
svg.selectAll("text.label")
.data(dataset)
.enter()
.append("text")
.attr("class", "label")
.text(function(d) {
console.log(output_format(d));
return output_format(d);
});
No other changes should be required.
I am beginning with d3.js and I would like to know the simplest way to show a box containing text (a tooltip) when my the mouse is over a node of my force-directed graph. Moreover, the text contained in this box must be custom for each node (something like function(d){return d.fullName;}))
Here is a sample code of what I have for now.
var node = vis.selectAll("g.node")
.data(json.nodes)
.enter().append("svg:g")
.attr("class", "node");
node.append("circle")
.attr("r", 12)
.style("fill", "orange");
Thanks in advance
By box, do you mean a tooltip? In Mike's examples, he uses this idiom:
node.append("title")
.text(function(d) { return d.fullName: });
(With other types of elements (divs only?) you can just use element.setAttribute("title", "title");.)