I'm new to D3 and am trying to modify Kerryrodden's sequences sunburst with displaying the breadcrumb on the Y (vertical) axis.
Here is an example of what I'm going for:
Here is a fiddle for where I'm at: http://jsfiddle.net/niceux/tth0goc7/
Basically, i've tried finding where the svg group is being appended, and swapping the x axis code with the y axis code on line 199 of the fiddle code:
entering.append("svg:text")
.attr("x", b.w / 2)
.attr("y", (b.h + b.t) / 2)
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; });
Here's a fiddle with the basics to get you started: http://jsfiddle.net/henbox/8m2gn7vw/2/
I made a few changes. Firstly, this was the code section determining how each breadcrumb polygon was positioned:
// Set position for entering and updating nodes.
g.attr("transform", function(d, i) {
return "translate(" + i * (b.w + b.s) + ", 0)";
});
Switching the translate to position breadcrumb nodes vertically was a case of fixing the x-axis at 0 and calculating the y-axis position instead, as well as switching the breadcrumb polygon width (b.w) for the height (b.h) like this:
return "translate(0, " + i * (b.h + b.s) + ")";
Next I needed to modify the <div id="sequence"></div> html element to fit the new shape of the breadcrumb trail. It was easiest to remove the sequence div all together and create a new div with id=leftsidebar based on the existing <div id="sidebar"> element used on the right side for the legend. I modified the CSS to give size and position for the new div.
Finally I moved the percentageString into the correct position, below the last breadcrumb node. For this I made a switch to x and y attributes from:
d3.select("#trail").select("#endlabel")
.attr("x", (nodeArray.length + 0.5) * (b.w + b.s))
.attr("y", b.h / 2)
to
d3.select("#trail").select("#endlabel")
.attr("x", b.w / 2)
.attr("y", (nodeArray.length + 0.5) * (b.h + b.s))
For further improvements, you'd probably want to re-shape the breadcrumb polygons (they point right at the moment which looks odd
Related
I am working with the Zoomable Sunburst on D3 Observable. I want to show the clicked label in the center circle.
So instead of this:
I need to see something like this:
But as you can see the label isn't remaining centered. I am currently using the following to add the label in the center circle on click, as you see in the previous GIF:
d3.select("#title").remove()
const main_title = g.append("text").attr("id", "title")
.attr("dx", function(d) {
return -20
})
.style("font-size", "18px").attr("text-anchor", "center")
.attr("transform", function(d, i) {
p.x = 9,
p.y = 10;
return "translate(" + p.x + "," + p.y + ")";
})
.text(p.data.name);
This is placed inside the clicked(p) function.
How can I ensure the label is centered regardless of text length. Also, ensure the label appears when the visual first loads, so you don't have to click on it to see the first one.
I noticed that my text is a bit offset, which is only notable when the spacing is limited. It is supposed to be centered (which it is wrt its baseline) but it makes it look shifted upwards when the spacing happens to be smaller than usual.
This is an example of it: jsFiddle. A very obvious occurence is if one clicks on the red category, number 5. Then, the most most yellow field is too narrow to harbor the text as it looks now.
var txt = d3.svg.arc().innerRadius(30).outerRadius(90);
grx.append("text")
.attr("text-anchor", "start")
.attr("transform", function(d) {
return "translate(" + txt.centroid(d) + ")"
+ "rotate(" + getRotation(d) + ")"; })
.text(function(d) { return d.data.key; });
function getRotation(d) {
var angle = (d.startAngle + d.endAngle) / Math.PI * 90 + 90;
return angle < 90 || angle > 270 ? angle : angle - 180;
}
How can I offset the text by an angle corresponding to the half of the height of the rendered text? Is it insanely difficult?
You may use the dy attribute to translate the text to the bottom. To shift it downwards half its height this value should be 0.5em. Looking at the output this seems too much, though, using 0.3em looks more pleasing to the eye.
grx.append("text")
.attr("class", "legendMain")
.attr("text-anchor", getAnchor)
.attr("dy", "0.3em") // Move downwards 30 percent its height
See this update JSFiddle for a working example.
I already have a donut chart in d3.js.
The animation for the labels is some thing like this right now :
starting point of labels : the labels are all in the center of the donut
ending point : they end up going behind the arcs.
Now below is what i am trying to achieve....
what i want to achieve :
I want to change the starting point of labels.
I want the labels to appear from behind the arcs of the donuts instead of
the center.
The ending point is fine like it is now.
Is there a way i can achieve this ?
i.e change the emission point of the labels instead from the center they should
appear from behind the arcs.
Here is the code that i am trying to modify :
var text=svg.selectAll('text')
.data(pie(dataset.data))
.enter()
.append("text")
.transition()
.duration(1000)
.attr("transform", function (d) {
console.log(d);
console.log(arc.centroid(d));
var c = arc.centroid(d),
x = c[0],
y = c[1],
h = Math.sqrt(x*x + y*y);
return "translate(" + (x/h * labelr) + ',' +
(y/h * labelr) + ")";
})
.attr("dy", ".4em")
.attr("text-anchor", "middle")
.text(function(d){
return d.data +"%";
})
.style({
fill:'#000',
'font-size':'11px'
});
Below is the link to the fiddle :
https://jsfiddle.net/ahc4wdjk/
In D3 transition selections, the starting value is the current atribute value. So, we start creating the texts behind the arcs:
.attr("x", function(d){
return arc.centroid(d)[0]
})
.attr("y", function(d){
return arc.centroid(d)[1]
})
I had a problem here, because your arcs don't show up at the same time. The solution was giving the texts an initial .attr("opacity", 0) and waiting a little bit (using delay(1000)).
Then, I used your code for the final position, but changing labelr to labelr = radius - 160;.
Here is the fiddle: https://jsfiddle.net/gerardofurtado/zrahm2h4/1/
(EDIT: viewBox and preserveAspectRatio are great, but aren't rendering properly in IE9, so I can't use that.)
I've been working on resizing this heatmap (here it is on a block). By selecting the width of a div, appending an SVG to it, and setting my SVG's width to that of the div, I've been able to make the heatmap responsive.
Nevertheless, I've run issues when I've tried to update the heatmap on resize. Here's the resize function:
d3.select(window).on("resize", resize);
function resize(){
marginHM = {top:35, right:0, bottom:50, left:30};
divWidthHM = parseInt(d3.select("#chartHM").style("width"));
widthHM = divWidthHM-marginHM.left-marginHM.right;
gridSize = Math.floor(widthHM/24);
legendElementWidth = gridSize*2.665;
heightHM = (9*gridSize)-marginHM.top-marginHM.bottom;
svgWidthHM = widthHM + marginHM.left+marginHM.right;
svgHeightHM = heightHM+marginHM.top+marginHM.bottom;
svgHM.select("svg").style("width", (svgWidthHM+20) + "px")
.style("height", (svgHeightHM+30) + "px");
dayLabels.attr("y", function (d, i){ return i*gridSize;})
.attr("transform", "translate(-6," + gridSize/1.5+")");
timeLabels.attr("x", function(d,i) {return i * gridSize;})
.attr("transform", "translate(" + gridSize/2+", -6)");
cards.attr("x", function(d) {return d.hour *gridSize; })
.attr("y", function(d) {return d.day * gridSize; })
.attr("width", gridSize)
.attr("height", gridSize);
d3.selectAll("rect.HMLegend")
.attr("x", function(d, i){ return legendElementWidth * i;})
.attr("y", 7.2*gridSize)
.attr("width", legendElementWidth)
.attr("height", gridSize/2);
d3.selectAll("text.HMLegendText")
.attr("x", function(d, i){ return legendElementWidth *i;})
.attr("y", 8*gridSize);
}
If you open the heatmap and drag the window to a wider size than it initially loaded in, you'll find that the heatmap grows, but the SVG's dimensions are cut off at the initial width; I find this really strange, considering I update the width in the resize function. You can decrease the width from its original value, and the map will size down, but you can't increase it above the original value of the width.
Additionally, I run into issues with the legend bar and legend labels. The the legend labels don't shift on window resize, and when you click back and forth between USA and New York, the legend colours often move off screen or show duplicates. Have been staring at this all evening, and am getting to the point where everything's blurring into one nonsensical line of code. Would really appreciate someone weighing in on exactly what it is I'm messing up!
I'm using the code from Mike Bostock's Radial Reingold–Tilford Tree pretty much as the example, but would like to control the position (just the radius) of the nodes according to a variable contained in each element of the JSON data.
I can do this for the nodes like this (using a linear scale on the variable I mentioned):
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + scale(d.variable) + ")"; })
But I can't figure out how the start and end positions of the links (which need to correspond with the nodes) are being controlled by the diagonal's default projection:
var diagonal = d3.svg.diagonal.radial()
.projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
Can anyone explain how this projection works, and what I should do to modify it to make the links start and end at a specific radius?