d3 y axis label position - javascript

I have a grouped bar chart design that has each bar amount immediately above the bar instead of the y axis bar on the far left.
I have added the text like so...
svg.selectAll(".text")
.data(data)
.enter()
.append("text")
.attr("class","label")
.attr("x", function(d) { return x1(d.rate) })
//.attr("y", function(d) { return y(d.value) + 1; })
.attr("dy", ".75em")
.text(function(d) {return d.value; });
But i cant seem to obtain the x and y values according to the bar position and the actual text of the d.value isn't getting inserted.
Sample here:
https://jsfiddle.net/6p7hmef1/7/

That's because the data bound to the texts that you're adding isn't right.
If you add a console.log as follows, you'll be able to see why the labels aren't being inserted. Check for the outputs in console. Console log fiddle
.text(function(d) {console.log(d); return d.value; });
One approach would be to append the texts to the bar groups ("slice" in your case). Just like you do for the bars. Here's a fiddle doing this:
JS Fiddle Demo
slice.selectAll(".text")
.data(function(d) { return d.values; })
.enter()
.append("text")
.attr("class","label");
slice.selectAll('text.label')
.attr("x", function(d) { return x1(d.rate)+ x1.rangeBand()/3 })
.attr("y", function(d) { return y(d.value) + 1; }).attr('dy', '-0.4em')
.text(function(d) {return d.value; });
This might look weird as the texts are shown before the transition of the bars. So changing the value of texts once the bars are shown seems like the right approach to me. (dx and dy attributes can be adjusted as per the requirement)
Here's the final fiddle:
JS FIDDLE
I'm using the "end" callback for every transition and changing the text values accordingly.
.each('end', function () {
d3.select(this.parentNode).selectAll('text.label')
.attr("x", function(d) { return x1(d.rate)+ x1.rangeBand()/3 })
.attr("y", function(d) { return y(d.value) + 1; }).attr('dy', '-0.4em')
.text(function(d) {return d.value; });
})
Hope this helps. :)
Let me know if any part of the code isn't understandable.

Related

Add tooltip to d3.js hierarchical bar chart

I am trying to add tooltip with mouseover hierarchical bars chart, as it is created by Mike Bostock here (https://bl.ocks.org/mbostock/1283663). I can't add tooltip by the traditional way, since the code is a bit different. Can anyone help me?
You could do it like this:
bar.append("text")
.attr("class", "moreText")
.attr("x", function(d) { return x(d.value) + 20; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.attr("fill", "none")
.text(function(d) { return d.value; })
in the bar function and add this to have the hover effect
bar.on("mouseover", function() {
d3.select(this).select(".moreText").attr("fill", "#333")
.attr("x", function(d) { return x(d.value) + 15; })
})
.on("mouseout", function() {
d3.select(this).select(".moreText").attr("fill", "none")
})
in the same function, adding the .attr("x", function(d) { return x(d.value) + 15; }) here to make sure we get the right coordinate for the right rectangle both before and after transitions as well and referencing the text by class like this:
d3.select(this).select(".moreText")
Here's a working plunker

Circles on top of bar chart d3.js

I am making grouped bar chart based on Mike Bostock's tutorial.
I can't figure out how to put circles on top of my bars to act as tooltip when hovering, just like in this tutorial except it's on bars and not on a line.
I tried appending the circles like this :
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) { return x1(d.name); })
.attr("cy", function(d) { return y(d.value); })
});
But I get NaN values. I am very confused about which variable I should use to get the right cx and cy.
Here is my code.
Any ideas ?
Thank you
You will get NaN values since your data join is not correct, you are trying to get values that are not currently present in your data. In order to get those values you would need to make a reference to data.years.
Here is my approach:
// Inheriting data from parent node and setting it up,
// add year to each object so we can make use for our
// mouse interactions.
year.selectAll('.gender-circles')
.data(function(data) {
return data.years.map(function(d) {
d.year = data.year;
return d;
})
})
.enter().append('circle')
.attr("class", function(d) {
return "gender-circles gender-circles-" + d.year;
})
.attr("r", 10)
.attr('cx', function(d) {
console.log(d)
return x1(d.name) + 6.5;
})
.attr('cy', function(d) {
return y(d.value) - 15;
})
.style('display', 'none'); // default display
// ....
// Using an invisible rect for mouseover interactions
year.selectAll('.gender-rect-interaction')
.data(function(d) { // Inheriting data from parent node and setting it up
return [d];
})
.enter().append('rect')
.attr("width", x0.rangeBand()) // full width of x0 rangeband
.attr("x", function(d) {
return 0;
})
.attr("y", function(d) {
return 0;
})
.attr("height", function(d) { // full height
return height;
})
.style('opacity', 0) // invisible!
.on('mousemove', function(d) { // show all our circles by class
d3.selectAll('.gender-circles-' + d.year)
.style('display', 'block');
})
.on('mouseout', function(d) { // hide all our circles by class
d3.selectAll('.gender-circles-' + d.year)
.style('display', 'none');
});
Working plnkr: https://plnkr.co/edit/oH4KXdxdIW82nLGv46NI?p=preview

D3 bar chart bar text labels not visible properly

I have a stacked bar chart in d3.js
For every stacked bar i have corresponding text value showing near stack itself.
problem is, some text values displaying are hidden behind bars, where as some are visible over bars. I want all text to visible over my bars. my code looks like,
bar.append("text")
.attr("x", function (d) { return x(d.x); })
.attr("y", function (d) { return y(d.y0 + d.y); })
.attr("dy", ".35em")
.attr('style', 'font-size:13px')
.text(function (d) { if (d.y != 0) { return "$" + d.y; } })
.style('fill', 'black');
Basically the issue related to z-index. But there is no z-index for SVG, so it can be fixed by reordering elements. Details here With JavaScript, can I change the Z index/layer of an SVG <g> element?
The simplest and fastest way:
To add .reverse() to the dataset.
// Create groups for each series, rects for each segment
var groups = svg.selectAll("g.cost")
.data(dataset.reverse())
.enter().append("g")
.attr("class", "cost")
.style("fill", function(d, i) { return colors[i]; });
The better way
To add different containers for bars and labels and put them in the right order in the DOM.
Try it http://jsfiddle.net/kashesandr/z90aywdj/

Transitioning Text in D3

I'm trying to add text to nodes that are created dynamically, specifically, like this graph:
http://bl.ocks.org/mbostock/999346
I am NOT looking to add text to collapsible graphs, but to add text to graphs that insert nodes at runtime, as shown in the above example.
So far I have the following additional code:
node.enter().append("text", "g")
.attr("x", function(d) { return (d.x);})
.attr("y", function(d) { return (d.y);})
.text(function(d) { return d.name; })
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; });
This adds text but it doesn't move when nodes are inserted.
The below lines appear to move the nodes and links in the example:
var t = svg.transition()
.duration(duration);
t.selectAll(".link")
.attr("d", diagonal);
t.selectAll(".node")
.attr("cx", function(d) { return d.px = d.x; })
.attr("cy", function(d) { return d.py = d.y; });
but adding a similar function for text:
t.selectAll(".text")
.style("fill-opacity", 1);
has no effect.
I would very much appreciate any guidance on this matter.
The nodes are all identified with d3.selectAll('.node'), so you need to give them the node class.
Also, the cx and cy attributes don't exist on text elements. you want x and y instead.
Example fiddle is here.

Looking for a way to display labels on sunburst chart (could not find a working example)

Thanks to someone's help (Brandon), I've been able to add tooltips to the sunburst charts.
I am still looking for a way to display the label of a path on the sunburst chart (and then have the dual mode tooltip + text).
The example that I'd like to improve is provided on jsfiddle.net/trakkasure/UPqX5/
I am looking for the code to add to the following code section:
path = svg.data([getData()]).selectAll("path")
.data(partition.nodes)
.enter().append("svg:path")
.attr("d", arc)
.style("fill", function(d) { return color((d.children ? d : d.parent).name); })
.on("click", magnify)
.on("mouseover", function(d) {
tooltip.show([d3.event.clientX,d3.event.clientY],'<div>'+d.name+'</div> <div>'+d.value+'</div>')
})
.on('mouseout',function(){
tooltip.cleanup()
})
.each(stash);
And I'd like to see the labels as shown on the example is provided on http://bl.ocks.org/910126. I can not get that example to work for me (I'm still new to D3)
I do recognize that there might be too much text on that chart, but in my scenario it is not a problem.
Can someone help me understand how to display all these labels on the chart?
Simply append svg:text elements to the canvas:
path.append("svg:text")
.attr("transform", function(d) { return "rotate(" + (d.x + d.dx / 2 - Math.PI / 2) / Math.PI * 180 + ")"; })
.attr("x", function(d) { return d.y; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d) { return d.name; });
However, in my edit, this will break your magnify function, so i create an svg group to hold together each pair of path and text. In my opinion, elements are better organized this way, easier to query in the future.
Note that you need to modify your magnify function to also animate the text, as for now it only animate the path and leave the text at their original position.
group = svg.data([getData()]).selectAll("path")
.data(partition.nodes)
.enter().append('svg:g');
//path variable is required by magnify function
path = group.append("svg:path")
.attr("d", arc)
.style("fill", function(d) { return color((d.children ? d : d.parent).name); })
.on("click", magnify)
.on("mouseover", function(d) {
tooltip.show([d3.event.clientX,d3.event.clientY],'<div>'+d.name+'</div><div>'+d.value+'</div>')
})
.on('mouseout',function(){
tooltip.cleanup()
})
.each(stash);
// you may need to assign the result to a variable,
// for example to animate the text in your magnify function,
// as shown in the path variable above
group.append("svg:text")
.attr("transform", function(d) { return "rotate(" + (d.x + d.dx / 2 - Math.PI / 2) / Math.PI * 180 + ")"; })
.attr("x", function(d) { return d.y; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d) { return d.name; });
Code was taken from your given example, however
I edited the x attribute into .attr("x", function(d) { return d.y; }) to properly position the text based on your data structure (the example uses Math.sqrt(d.y)). I also modify the text function to return d.name
here is the jsFiddle

Categories