D3.js: 原地旋转文本
D3.js: Rotate text on-spot
我有一个包含 38 个项目的饼图。半径很大,因此文字向内转。我唯一的问题是文本倒置了。我试图通过正常旋转来解决这个问题,但这不起作用,因为它围绕我整个图形的中心旋转。我搜索了答案并发现了相似之处。我试图将 that code 用于我自己的目的但失败了。
我还检查了一个example on b.locks,据我了解:他们在这里旋转,然后将它放在原来的位置。
我的文字做了很多事情,但几乎不是我想要的。在当前状态下,它将所有内容堆叠在我的图表中间。
这是我的代码:
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")
//
.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")
})
我还在下面的简化版本中添加了我的数据集。
由于我是 D3 的新手,如果有人能告诉我如何实现文本在现场旋转或指导我如何实现我的目标,我将不胜感激 :) 非常感谢。
{ "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"
}
]
}
要围绕其中心旋转某物,您需要将其中心移动到 (0, 0),他们旋转它,然后将其移回。所以在你添加转换的地方,做:
// 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;
}
}
});
我有一个包含 38 个项目的饼图。半径很大,因此文字向内转。我唯一的问题是文本倒置了。我试图通过正常旋转来解决这个问题,但这不起作用,因为它围绕我整个图形的中心旋转。我搜索了答案并发现了相似之处。我试图将 that code 用于我自己的目的但失败了。
我还检查了一个example on b.locks,据我了解:他们在这里旋转,然后将它放在原来的位置。
我的文字做了很多事情,但几乎不是我想要的。在当前状态下,它将所有内容堆叠在我的图表中间。
这是我的代码:
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")
//
.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")
})
我还在下面的简化版本中添加了我的数据集。 由于我是 D3 的新手,如果有人能告诉我如何实现文本在现场旋转或指导我如何实现我的目标,我将不胜感激 :) 非常感谢。
{ "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"
}
]
}
要围绕其中心旋转某物,您需要将其中心移动到 (0, 0),他们旋转它,然后将其移回。所以在你添加转换的地方,做:
// 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;
}
}
});