我正在尝试将文本放置在基于d3.js的Sunburst图表的楔形内部时遇到问题。即使在缩放时,text
元素似乎也没有按照需要定位..
var slices = svg.selectAll(".form")
.data(function(d) { return data_slices; })
.enter()
.append("g");
slices.append("path")
.attr("d", arc)
.attr("id",function(d,i){return d[2]+""+i;})
.style("fill", function(d) { return color(d[2]);})
.on("click",animate)
.attr("class","form")
.append("svg:title")
.text(function(d) { return Math.round(d[0]*100)/100 +" , "+ Math.round(d[1]*100)/100; });
//Something needs to change below....
slices.append("text")
.style("font-size", "10px")
.attr("x", function(d) { return y(d[1]); })
.attr("transform", function(d) { return "rotate(" + this.parentNode.getBBox().width + ")"; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d){return d[2]})
.attr("pointer-events","none");
可能出现什么问题?任何人都可以告诉我或指导我如何将<text>
置于svg <path>
内。看起来解决方案是对此的一个小调整,但我甚至无法达到它试了很久..
任何有关解决方案的帮助/评论都将不胜感激......在此先感谢..
答案 0 :(得分:3)
我认为这与您的目标接近:http://jsfiddle.net/4PS53/3/
所需的更改如下:
function getAngle(d) {
// Offset the angle by 90 deg since the '0' degree axis for arc is Y axis, while
// for text it is the X axis.
var thetaDeg = (180 / Math.PI * (arc.startAngle()(d) + arc.endAngle()(d)) / 2 - 90);
// If we are rotating the text by more than 90 deg, then "flip" it.
// This is why "text-anchor", "middle" is important, otherwise, this "flip" would
// a little harder.
return (thetaDeg > 90) ? thetaDeg - 180 : thetaDeg;
}
slices.append("text")
.style("font-size", "10px")
.attr("x", function(d) { return d[1]; })
// Rotate around the center of the text, not the bottom left corner
.attr("text-anchor", "middle")
// First translate to the desired point and set the rotation
// Not sure what the intent of using this.parentNode.getBBox().width was here (?)
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")" + "rotate(" + getAngle(d) + ")"; })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d){return d[2]})
.attr("pointer-events","none");
现在,为了使其适用于缩放,参考点发生变化,我们需要更多的基础设施。
g.form-container
而不仅path.form
可见/不可见。这意味着我们不必担心标签会单独消失。 (我添加了form-container
类。)计算新点并为其计算centroid
和rotation
。这有点棘手,但并不太难:
function change_ref(data_point, reference_point) {
return [
get_start_angle(data_point, reference_point),
get_stop_angle (data_point, reference_point),
data_point[2],
get_level (data_point, reference_point)
];
}
// And while doing transitioning the `text.label`:
svg.selectAll('.label')
.filter(
function (b)
{
return b[0] >= new_ref[0] && b[1] <= new_ref[1] && b[3] >= new_ref[3];
}
).transition().duration(1000)
.attr("transform", function(b) {
var b_prime = change_ref(b, d);
return "translate(" + arc.centroid(b_prime) + ")" +
"rotate(" + getAngle(b_prime) + ")";
})
我已将课程label
添加到text
。
更新了演示: http://jsfiddle.net/4PS53/6/
但是,我认为可能有更好的方式来呈现这些数据,尤其是。如果您允许缩放和平移:D3 put arc labels in a Pie Chart if there is enough space
答案 1 :(得分:1)
我在musically_ut代码中做了一些改进。
现在您可以从一个数据更改为另一个数据。
$('#change').click(function () {
if (animating) {
return;
}
if (currentSet == 0) {
currentSet = 1;
svg.selectAll(".form").filter(
function (d) {
return d[0] >= ref[0] && d[1] <= ref[1] && d[level_index] >= ref[level_index];
}
)
.transition().duration(1000)
.attrTween("d", changeDatarebaseTween(0, 1, 2, 3));
svg.selectAll('.label').filter(
function (d) {
return d[0] >= ref[0] && d[1] <= ref[1] && d[level_index] >= ref[level_index];
}
)
.transition().duration(1000)
.attr("transform", function (b) {
var b_prime = change_ref_CD(b);
return "translate(" + arc.centroid(b_prime) + ")" +
"rotate(" + getAngle(b_prime) + ")";
})
}
else {
currentSet = 0;
svg.selectAll(".form").filter(
function (d) {
return d[2] >= ref[2] && d[3] <= ref[3] && d[level_index] >= ref[level_index];
}
)
.transition().duration(1000).attrTween("d", changeDatarebaseTween(2, 3, 0, 1));
svg.selectAll('.label').filter(
function (d) {
return d[2] >= ref[2] && d[3] <= ref[3] && d[level_index] >= ref[level_index];
}
)
.transition().duration(1000)
.attr("transform", function (b) {
var b_prime = change_ref_CD(b);
return "translate(" + arc.centroid(b_prime) + ")" +
"rotate(" + getAngle(b_prime) + ")";
})
}
setTimeout(function () {
animating = false;
}, 1000);
});
编辑:http://jsfiddle.net/k1031ogo/3/
(代码可能更干净,复制/粘贴太多)