D3.JS <tspan> rotation in sunburst - d3.js

I am building my own sunburst diagram from this example
by adding multiline captions as .
for(i = 0; i < MAX_LINES; i++){
var text = g.append("text")
.attr("transform", function(d) { return "translate(" + getCentroid(d) + ")rotate(" + textRotation(d) + ")"; })
.attr('text-anchor', function (d) { return textRotation(d) > 180 ? "end" : "start"; })
.attr("dx", "0")
.attr("dy", "0em")
.attr("class", function(d) { return setStyle(d); })
.style("fill", function(d) { return setColor(d); })
.style("text-anchor", "middle")
.append("tspan")
.attr("dy", function(d) { return getDY(d, i); } )
.text(function(d) { return getLine(d, i); });
//.text(function(d) { return d.name; });
}
This works absolutely fine on initial state, but when you are
zooming it by clicking on certain partition everything becomes
messy. The script only moves first line element and doesn't
hide other elements shouldn't be on screen.
.duration(500)
.attrTween("d", arcTween(d))
.each("end", function(e, i) {
if (e.x >= d.x && e.x < (d.x + d.dx)) {
var arcText = d3.select(this.parentNode).select("text");
arcText.transition().duration(750)
.attr("opacity", 1)
.attr("transform", function(d) { return "translate(" + getCentroid(d) + ")rotate(" + textRotation(d) + ")"; })
.attr('text-anchor', "middle")
}
});
}
});
How I can transform for every partition?
I have tried to do selection by "tspan" or its style class.
Is it possible to completely renew block by reassigning name
and recreating 's

Related

How to update data elements within a transition without deleting a re-creating everything?

I'm using d3js v3 have a heat map that upon changing a ratio button selection I would switch the data from one dataset to another. The initialization requires a lot of steps e.g.
var svg = d3.select("#myId").append("svg");
...
var heatNode = svg.append("g");
heatNode.selectAll(".cellrect")
.data(data, function(d) { return d.row + ":" + d.col; })
.enter()
.append("rect")
.attr("x", function(d) { return (d.col - 1) * (cellWidth + cellMargin); })
.attr("y", function(d) { return (d.row - 1) * (cellHeight + + cellMargin); })
.attr("class", function(d) { return "cell cell-border cr" + (d.row-1) + " cc" + (d.col-1); })
.attr("width", cellWidth)
.attr("height", cellHeight)
.style("fill", function(d) { return colorScale(d.value); })
.on("mouseover", function(d) {
// highlight text
d3.select(this).classed("cell-hover", true);
d3.selectAll(id + " .rowLabel").classed("text-highlight", function(r, ri) { return ri == (d.row - 1); });
d3.selectAll(id + " .colLabel").classed("text-highlight", function(c, ci) { return ci == (d.col - 1); });
})
.on("mouseout", function(d) {
d3.select(this).classed("cell-hover", false);
d3.selectAll(id + " .rowLabel").classed("text-highlight", false);
d3.selectAll(id + " .colLabel").classed("text-highlight", false);
});
and now I get new data and would like to update only the fill color and nothing else. So I have tried without succcess:
heatNode.selectAll(".cellrect").transition().duration(2000)
.data(newData, function(d) { return d.row + ":" + d.col; })
.style("fill", function(d) { return colorScale(d.value); });
The only way that has worked for me so far is doing an ugly:
heatNode.selectAll("*").transition().duration(2000).remove();
and recreating everything again, however, not even then the transition works for me.
The code seems right but you need to add cellrect class to the first selection if you want to use this class to select the elements again
heatNode.selectAll(".cellrect")
.data(data, function(d) { return d.row + ":" + d.col; })
.enter()
.append("rect")
.attr("x", function(d) { return (d.col - 1) * (cellWidth + cellMargin);})
.attr("y", function(d) { return (d.row - 1) * (cellHeight + + cellMargin); })
.attr("class", function(d) { return "cellrect cell cell-border cr" + (d.row-1) + " cc" + (d.col-1); })
...

D3 V4 General Update Pattern for Pack Layout

I am trying to use General Pattern to update my Pack Layout but have not been successful. Below is my fiddle. So when Randomize Data is clicked the data should be updated.
Here is my full fiddle.
function update() {
root = d3.hierarchy(data)
.sum(function(d) {
return d.size;
})
.sort(function(a, b) {
return b.value - a.value;
});
var node = g.selectAll(".node")
.data(pack(root).descendants())
.enter().append("g")
.attr("class", function(d) {
return d.children ? "node" : "leaf node";
})
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title")
.text(function(d) {
return d.data.name + "\n" + format(d.value);
});
node.append("circle")
.attr("r", function(d) {
return d.r;
});
node.filter(function(d) {
return !d.children;
}).append("text")
.attr("dy", "0.3em")
.text(function(d) {
return d.data.name.substring(0, d.r / 3);
});
}
Your code only have the "enter" selection. You're missing an "update" selection (and eventually an "exit" selection).
The "update" selection can be something like this:
var nodeUpdate = g.selectAll(".node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});;
var circleUpdate = nodeUpdate.select("circle")
.attr("r", function(d) {
return d.r;
});
Check the fiddle: https://jsfiddle.net/or7pLnjp/

D3, get X values (date) from multiple Y values, create text

I have searched through many answers about getting X (date) values given a Y. Most revolve around the scale.invert() function. However, I am having trouble implementing this in my task.
Task: I am creating a hydrograph (time-series line graph of water level). I'm also plotting min/max points, and median line, all with text labels. See first image. This is a 'proof of concept', so I'm ok with things being a little dirty.
Problem: I want to add the corresponding dates for those min/max points, and I can't figure out how. One caveat, sometimes there are multiple points with same min or max value. I am unable to: A) get the correct date for the point, and B) add the date for each instance (all mins and maxes, if there are multiples) to the text. Thanks for any help or direction.
Some of the code (that I think is immediately relevant) is below. Here's the codepen. I'm sure it's not pretty, I'm new to D3 and javascript.
...
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Water Level (ft)");
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
var extent = d3.extent(data, function(d) {
return d.level
})
var min = extent[0]
var max = extent[1]
var median = d3.median(data, function(d) {
return d.level
})
var medianLine = svg.append("line")
.attr("class", "medianLine")
.attr("y1", y(median))
.attr("y2", y(median))
.attr("x1", 0)
.attr("x2", width)
var points = svg.selectAll("g")
.data(data)
.enter()
.append("g")
.filter(function(d) {
return d.level === min || d.level === max;
})
points.append("circle")
.attr("class", "dot")
.attr("cx", function(d) {
return x(d.date);
})
.attr("cy", function(d) {
return y(d.level);
})
.attr("r", 5)
points.append("text")
.attr("x", function(d) {
return x(d.date);
})
.attr("y", -20)
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.style("text-anchor", "middle")
points.selectAll("circle")
.style("fill", function(d) {
if (d.level === min) {
return "red"
} else {
return "#009933"
};
});
points.selectAll("text")
.text(function(d) {
if (d.level === min) {
return "Min: " + min
} else if (d.level === max) {
return "Max: " + max
}
})
.style("fill", function(d) {
if (d.level === min) {
return "red"
} else if (d.level === max) {
return "#246B24"
}
})
svg.append("text")
.attr("transform", "translate(" + (width + 3) + "," + y(median) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.style("fill", "#cc6600")
.text(function(d) {
return "Median: " + median
})
...
Well after a quick peek to the code the date is a property of your data so there should not be any problem accessing it e.g.
points.selectAll("text")
.text(function(d) {
// date is accessible through d.date
if (d.level === min) {
return "Min: " + min + ' ' + d.date
} else if (d.level === max) {
return "Max: " + max + ' ' + d.date
}
})
If you want to format the date you can read about time formatting in d3

d3.js - Text inside arc is misaligned/overlapped

I am drawing a pie chart and in each arc i write the text in the centre. However when the arc is too small, the text gets misaligned. How do i restrict writing the text if the arc is too thin. Is there a way to identify the arc and not write the text.
My code:
var arc = d3.svg.arc()
.outerRadius(radius - 45)
.innerRadius(radius -200);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {return d.Components;});
var g = svg.selectAll(".arc")
.data(pie(newdata))
.enter().append("g")
.attr("class", "arc")
.attr("id", function(d,i) {return "group" + i})
g.append("path")
.attr("d", arc)
.style("fill","#FFFFFF")
.transition()
.ease("bounce")
.duration(1000)
.delay(function(d, i) {return i * 500;})
.style("fill", function(d,i)
{
var c = d.data.Source;
if (c=="GREEN")
{
return "#78a22f";
}
else if (c=="RED")
{
return "#a00000";
}
else if (c=="AMBER")
{
return "#Ffb400";
}
else
{
return "#DADCF6";
}
});
g.append("text")
.attr("transform", function(d)
{
//comment
var c = arc.centroid(d);
var param,param1
param = c[1]- 20;
param1= c[0]- 38;
return "translate(" + param1 + "," + param + ")";
})
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("style","font-family: Arial;border: solid 1px" )
.transition()
.ease("bounce")
.duration(1000)
.delay(function(d, i) {return i * 500;})
.text(function(d) {
return ((d.data.Status));
}
});
g.append("text")
.attr("transform", function(d)
{
var c = arc.centroid(d);
var param = c[1];
var param1=c[0];
return "translate(" + param1 + "," + param + ")";
})
.attr("dy", ".35em")
.style("text-anchor", "middle")
.transition()
.ease("bounce")
.duration(1000)
.delay(function(d, i) {return i * 500;})
.text(function(d) {
if (eval(d.data.Components) >0)
{
return (Number(d.data.Components).toFixed(0)) + " (" + (Number(d.data.Percentage).toFixed(1) + "%)");
}
});
data is like:
"Source","Components","Percentage","Business Unit","Status","BUId"
"RED","20","4.77","Financial & Risk - ALL","Analyzed","67001003"
"AMBER","2","0.48","Financial & Risk - ALL","Identified","67001003"
"GREEN","21","5.01","Financial & Risk - ALL","Approved","67001003"
"PALEBLUE","83","19.81","Financial & Risk - ALL","Unmapped","67001003"
"GREY","293","69.93","Financial & Risk - ALL","Not Applicable","67001003"

Tooltip in bubble chart using d3.js

I am using d3.js for bubble chart.its working fine but i need to write custom tool tip for the data which i am showing.currently i just appended one title tag so it just showing one data with tooltip
what if i have more data to show and want to show in form of a table.
Here is my code.
d3.json("data/bubble.json", function(error, root) {
var node = svg.selectAll(".node")
.data(bubble.nodes(classes(root))
.filter(function(d) { return !d.children; }))
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("title")
.text(function(d) { return d.className + ": " + format(d.value); });
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.packageName); });
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.className.substring(0, d.r / 3); });
});

Resources