Reputation: 35
I have a pie chart with a 38 items in it. The radius is quite big and thus the text turns inward. The only problem I have is that the text stands upside down. I tried to fix that with just a normal rotation but that doesn't work, as it rotates around the center of my whole graph. I searched for answers and found smth similar. I tried to use that code for my own purposed but failed.
I also checked an example on b.locks and as far as I understand it: Here they rotate and then just place it at the spot where it was before.
My text did a lot of stuff but hardly what I wanted. With the current state it stacks everything in the middle of my graph.
Here is my code:
var margin = { left:80, right:100, top:50, bottom:100 },
height = 1200 - margin.top - margin.bottom,
width = 1280 - margin.left - margin.right,
cwidth = 50;
var svg = d3.select("#pie-chart svg")
.append("g")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + 525 + "," + 450 + ")")
.append("g")
/*gives the same numeric value to every object in the datafile (cuz they dont have numeric values) */
var pie = d3.pie()
.value(function(d){return 1})
;
//load data
d3.json("./data/unidata.json").then(function(data){
//console.log(data);
var arc = d3.arc();
var gs = svg.selectAll("g")
.data(d3.values(data))
.enter()
.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")")
;
var arcIndexDictionary = {};
var arcRingIndexSizeDictionary = {};
// Visible arc
gs.selectAll("path")
.data(function(d,i) {
return pie(d).map(function(e){e.ringIndex = i; return e});
})
.enter()
.append("path")
.attr("class", "nameArc")
.attr("id", function(d,i) {
return d.data.name + "nameArc_"+i+i;
})
.attr("d",
function(d, i) {
var innerRadius = cwidth * d.ringIndex;
var outerRadius = cwidth * (d.ringIndex + 1);
var outerRadiusSlim = cwidth * (d.ringIndex + 1) + 2 * cwidth;
// stores how many items are there in a ring in order to decide which text to flip
arcRingIndexSizeDictionary[d.ringIndex] = i;
// Main Arc - draws the rings
if (d.ringIndex == 0){
arcIndexDictionary[d.data.name + "nameArc_"+i] = (innerRadius + outerRadius) / 2.0;
return arc.innerRadius(innerRadius).outerRadius(outerRadius)(d);
}
else if (d.ringIndex == 1){
arcIndexDictionary[d.data.name + "nameArc_"+i] = (innerRadius + outerRadiusSlim) / 2.04;
return arc.innerRadius(innerRadius).outerRadius(outerRadiusSlim)(d);
}
}
)
.attr("fill", "grey")
;
// Placing text
gs.selectAll(".nameText")
.data(function(d,i) {
return pie(d).map(function(e){e.ringIndex = i; return e});
})
.enter()
.append("text")
.attr("class", "nameText")
.attr('dy', function(d, i, array){
var ringItemCount = arcRingIndexSizeDictionary[d.ringIndex];
})
.append("textPath")
.attr("xlink:href",function(d, i, array){
return "#" + d.data.name + "nameArc_"+i+i;
})
.style("text-anchor", function(d, i){
var ringItemCount = arcRingIndexSizeDictionary[d.ringIndex];
if(d.ringIndex == 1 && i <= ringItemCount/2) {
return "start"; //HERE
} else {
return "start"
}
})
.attr("startOffset", function(d, i){
if(d.ringIndex == 1 && i <= ringItemCount/2)
return "50%";
if(d.ringIndex == 1) return "12%";
var ringItemCount = arcRingIndexSizeDictionary[d.ringIndex];
})
.text(function(d, i, array){
if (d.ringIndex > 0)
{return d.data.name};
})
.style('font-family', 'arial')
.attr('font-size', function(d){
if(d.ringIndex > 1){return '13px'} else {
return '9px';
}})
;
// ROTATE
d3.selectAll("text")
// https://stackoverflow.com/questions/26049488/how-to-get-absolute-coordinates-of-object-inside-a-g-group
.attr("transform", function(d, i){
if(d != undefined)
{
var ringItemCount = arcRingIndexSizeDictionary[d.ringIndex];
var rightPieCount = ringItemCount / 2;
var halfPoint = rightPieCount / 2;
if(d.ringIndex == 1 && i <= ringItemCount/2)
{
// if you add 1 to x you need to add 180 / 19 * i
var locationData = this.getBBox();
var centerX = locationData.x + (locationData.width / 2);
var centerY = locationData.y + (locationData.height / 2);
// Fix their centralized locations
/*
if (locationData.y < 0){
centerX = centerX + i * 7;
centerY = centerY - (halfPoint - i) * 6;
} else {
centerX = centerX + (rightPieCount - i) * 7;
centerY = centerY - (-(halfPoint - i) * 6);
} */
console.log(centerX, centerY);
var result = "";
result += 'translate(' + centerX + ',' + centerY + ')';
result += 'rotate(180)';
return result;
}
}
})
;
// middle text
gs.append("text")
.attr("text-anchor", "middle")
.attr('font-size', '0.8em')
.attr('font-family', 'arial')
.style('fill', 'white')
.text("Inf FB")
})
I'm also adding my data-set in a shortened version below. As I am new to D3 I would really appreciate if someone could tell me how to achieve that the text rotates on spot or direct me in another direction on how to achieve my goal :) Thanks a lot.
{ "Leitsatz": [],
"Profs": [
{
"name": "Softwarekonstruktion"
},
{
"name": "Verteilte Systeme"
},
{
"name": "Angew. Softwaretechnik"
},
{
"name": "Sicherheit"
},
{
"name": "(W1) Sicherheit/ Sicherheitsmgmt."
},
{
"name": "Rechennetze"
},
{
"name": "Theoretische Inf."
},
{
"name": "(W1) Theoretische Inf.)"
},
{
"name": "(W1) Informatikbildung)"
},
{
"name": "(W1) Mobile Services"
},
{
"name": "(W1TT) Informatik"
},
{
"name": "Wiss. Rechnen (DKRZ)"
},
{
"name": "Wiss. Visualisierung (Dir. RRZ)"
},
{
"name": "Daten Enginieering"
},
{
"name": "Simulation & Visualisierung"
},
{
"name": "Alg. Molekulares Design"
},
{
"name": "(W1) Angewandte Bioinf."
},
{
"name": "Rechnerg. Bioinformatik"
},
{
"name": "Maschinelles Lernen"
},
{
"name": "Autonome Systeme"
},
{
"name": "(W1TT) Sem. Systeme"
},
{
"name": "Wissenstechnologien"
},
{
"name": "Signalverarbeitung"
},
{
"name": "Bildverarbeitung"
},
{
"name": "(W1TT) Assistenzsysteme"
},
{
"name": "Sprachverarbeitung"
},
{
"name": "Sprachtechnologie"
},
{
"name": "Multimodale Systeme"
},
{
"name": "Mensch-Computer-Interaktion"
},
{
"name": "Usability & Softwareergonomie"
},
{
"name": "Ethik in der Informationstechnik"
},
{
"name": "IT-Gestaltung"
},
{
"name": "(W1TT) Wirtschaftsinformatik"
},
{
"name": "(W1TT) Betriebssystem"
},
{
"name": "(W1TT) Adaptive Systeme"
},
{
"name": "IT Management"
},
{
"name": "Digital Technochange"
},
{
"name": "Datenbanken"
}
]
}
Upvotes: 0
Views: 589
Reputation: 10979
To rotate something about its centre you need to move its centre to (0, 0), them rotate it, then move it back. So where you are adding the transforms, do:
// ROTATE
d3.selectAll("text")
.attr("transform", function(d, i) {
if (d !== undefined) {
var ringItemCount = arcRingIndexSizeDictionary[d.ringIndex];
if (d.ringIndex == 1 && i <= ringItemCount / 2) {
var locationData = this.getBBox();
var centerX = locationData.x + (locationData.width / 2);
var centerY = locationData.y + (locationData.height / 2);
var result = 'translate(' + centerX + ',' + centerY + ')';
result += 'rotate(180)';
result += 'translate(' + (-centerX) + ',' + (-centerY) + ')';
return result;
}
}
});
Upvotes: 2