如何使用d3.js在Sunburst图表上定位文本标签
我正在尝试将文本放置在基于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");
这是图表的小提琴
小提琴
有什么可能的问题? 并且任何人都可以告诉我或指导我如何在 svg
定位
看起来像解决方案是一个小调整,但我甚至在尝试了很长时间后仍然无法达到它时间..
任何有关解决方案的帮助/评论都将不胜感激……在此先感谢..
我认为这接近你要达到的目标: 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会将圆弧标签放在饼图中
我在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/
(代码可能更干净,复制/粘贴太多)