圆形图上的弯曲标签(D3.js)

时间:2016-12-26 11:26:57

标签: javascript d3.js svg

所以,我基本上试图用D3.js(v4)和JSON数据制作一个多级循环分区(又名旭日图)。

我放置了一些标签,这些标签必须具有不同的角度,具体取决于它们在分区上的水平(圆圈):
- 等级< 3必须是弯曲的"跟随"弧半径。
- level == 3必须是直线且垂直于圆弧半径。

我没有使用textPath标签,因为我在SVG中并没有真正的经验,看起来对我来说过于复杂,而且我真的不知道如何使用它。

这里是我的代码(没有JSON,但这是一个非常经典的代码,如果需要,我可以添加一部分代码):

var width = 800;
var height = 800;
var radius = 400;
var formatNumber = d3.format(",d");
var x = d3.scaleLinear().range([0, 2 * Math.PI]);
var y = d3.scaleSqrt().range([0, radius]);

var arc = d3.arc()
    .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x0))); })
    .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x1))); })
    .innerRadius(function(d) { return setRadius("inner", d.data.level); })
    .outerRadius(function(d) { return setRadius("outer", d.data.level); });

var svg = d3.select("#chart")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width/2 + "," + (height/2) + ")");

var hierarchy = d3.hierarchy(dataset)
    .sum(function(d) { return d.size; });

var partition = d3.partition();

svg.selectAll("path")
    .data(partition(hierarchy).descendants())
    .enter().append("path")
    .attr("id", function(d, i){ return "path" + i; })
    .attr("d", arc)
    .attr("stroke", "white")
    .attr("stroke-width", "1px")
    .style("fill", function(d) { return (d.data.color) ? d.data.color : 'black'; });

svg.selectAll("text")
    .data(partition(hierarchy).descendants())
    .enter().append("text")
    .attr("transform", function(d){ return setLabelPosition(d); })
    .attr("text-anchor", "middle")
    .attr("alignment-baseline", "middle")
    .attr("font-size", "18px")
    .attr("fill", function(d){ return d.data.textcolor; })
    .text(function(d){ if(parseInt(d.data.level) > 0 && parseInt(d.data.level) < 4){ return (d.data.name).toUpperCase(); }});

d3.select(self.frameElement)
    .style("height", height + "px");

function setRadius(side, level){
    var result = 0;
    var innerValues = [0, 120, 180, 240, 365];
    var outerValues = [0, 180, 240, 365, 400];
    if(!side){
        throw error;
    }
    if(side === "inner"){
        result = innerValues[level];
    }
    if(side === "outer"){
        result = outerValues[level];
    }
    return result;
};

function setLabelPosition(d){
    var result = '';
    var angle = 0;
    var centroid = arc.centroid(d);
    if(parseInt(d.data.level) === 3){
        angle = (180/Math.PI * (arc.startAngle()(d) + arc.endAngle()(d))/2 - 90);
        if(angle > 90){
            angle = angle - 180;
        }
        result = "translate(" + centroid + ")rotate(" + angle + ")";
    } else {
        angle = (180/Math.PI * (arc.startAngle()(d) + arc.endAngle()(d))/2);
        result = "translate(" + centroid + ")rotate(" + angle + ")";
    }
    return result;
};

结果:
sunburst diagram
我的问题是,如何曲线化这些1级&amp; 2个标签(如带有红色边框的标签),但保留我目前的lvl 3标签。

这真的是一个痛苦的头脑,我做了很多搜索(在Google和SO上),但我没有找到任何令人满意的答案。
如果可能的话,不使用textPath的解决方案会很棒,但欢迎任何建议。

非常感谢大家,对不起我的英语(因为你可能看到它不是我的出生语言)。

PS:这是D3.js v4。

0 个答案:

没有答案