在d3中包含单词以在一行中获得一个单词

时间:2017-03-13 17:05:55

标签: javascript html css d3.js svg

如何使用commonly used word wrap function将我的圆环图表标签包装在一行中?或者还有其他方法吗?

var div = d3.select("body").append("div").attr("class", "toolTip");

var w = 650;
var h = 400;
var r = 100;
var ir = 75;
var textOffset = 24;
var tweenDuration = 1050;

//OBJECTS TO BE POPULATED WITH DATA LATER
var lines, valueLabels, nameLabels;
var pieData = [];    
var oldPieData = [];
var filteredPieData = [];

//D3 helper function to populate pie slice parameters from array data
var donut = d3.layout.pie()
.value(function(d){
    return d.itemValue;
});

//D3 helper function to draw arcs, populates parameter "d" in path object
var arc = d3.svg.arc()
    .startAngle(function(d){ return d.startAngle; })
    .endAngle(function(d){ return d.endAngle; })
    .padAngle(.02)
    .innerRadius(ir)
    .outerRadius(r);

// data
var data;
var dataStructure = [{
    "data":[{
        "itemLabel":"no patients",
        "itemValue":27,
        "color": "#2FB9A1"
    },{
        "itemLabel":"1 patient",
        "itemValue":11,
        "color": "#F3B4B5"
    },{
        "itemLabel":"2 patients",
        "itemValue":33,
        "color": "#EC8E8F"
    },{
        "itemLabel":"3 or more patients",
        "itemValue": 21,
        "color": "#DA7C36"
    }],
    "label":"Patients"
}];

// CREATE VIS & GROUPS 
var vis = d3.select("#pie-chart").append("svg:svg")
    .attr("width", w)
    .attr("height", h);

//GROUP FOR ARCS/PATHS
var arc_group = vis.append("svg:g")
    .attr("class", "arc")
    .attr("transform", "translate(" + (w/2) + "," + (h/2) + ")");

//GROUP FOR LABELS
var label_group = vis.append("svg:g")
    .attr("class", "label_group")
    .attr("transform", "translate(" + (w/2) + "," + (h/2) + ")");

//GROUP FOR CENTER TEXT  
var center_group = vis.append("svg:g")
    .attr("class", "center_group")
    .attr("transform", "translate(" + (w/2) + "," + (h/2) + ")");

var centerText='';

// to run each time data is generated
function update(number) {
    data = dataStructure[number].data;
    oldPieData = filteredPieData;
    pieData = donut(data);

    var sliceProportion = 0; //size of this slice
    filteredPieData = pieData.filter(filterData);
    function filterData(element, index, array) {
        element.name = data[index].itemLabel;
        element.value = data[index].itemValue;
        element.color = data[index].color;
        sliceProportion += element.value;
        return (element.value > 0);
    }

    //DRAW ARC PATHS
    paths = arc_group.selectAll("path")
        .data(filteredPieData);
    paths.enter()
        .append("svg:path")
        .attr("stroke", "transparent")
        .attr("stroke-width", 0.5)
        .attr("fill", function(d, i) { return d.color; })
        .transition()
        .duration(tweenDuration)
        .attrTween("d", pieTween);

    paths.transition()
        .duration(tweenDuration)
        .attrTween("d", pieTween);

    paths.exit()
        .transition()
        .duration(tweenDuration)
        .attrTween("d", removePieTween)
        .remove();

    paths.on("mousemove", function(d) {
            div.style("left", d3.event.pageX+10+"px");
            div.style("top", d3.event.pageY-25+"px");
            div.style("display", "inline-block");
            div.html((d.data.itemLabel)+"<br>"+(d.data.itemValue));
    });

    paths.on("mouseout", function(d){
        div.style("display", "none");
    });

    //DRAW LABELS WITH ENTITY NAMES
    nameLabels = label_group.selectAll("text.units")
        .data(filteredPieData)
        .attr("dy", function(d) {
            if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) {
                return 17;
            } else {
                return 5;
            }
        })
        .attr("text-anchor", function(d) {
            if ((d.startAngle+d.endAngle)/2 < Math.PI ) {
                return "beginning";
            } else {
                return "end";
            }
        })
        .text(function(d) {
            return d.name;
        });

    nameLabels.enter()
        .append("svg:text")
        .attr("class", "units")
        .attr("transform", function(d) {
            return "translate(" + Math.cos(((d.startAngle+d.endAngle - Math.PI)/2)) * (r+textOffset) + "," + Math.sin((d.startAngle+d.endAngle - Math.PI)/2) * (r+textOffset) + ")";
        })
        .attr("dy", function(d) {
            if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) {
                return 18;
            } else {
                return 5;
            }
        })
        .attr("text-anchor", function(d){
            if ((d.startAngle+d.endAngle)/2 < Math.PI ) {
                return "beginning";
            } else {
                return "end";
            }
        }).text(function(d){
            return d.name;
        });

    nameLabels.transition()
        .duration(tweenDuration)
        .attrTween("transform", textTween);

    nameLabels.exit().remove(); 

    var total = 0;
    pieData.forEach(function(d) { total+=(d.value*1); });
    center_group.selectAll('text')
        .data([total])
        .enter()
        .append('text')
        .text(function(d) {
            return d;
        })
        .attr('class','value')
        .attr('dy', 8)
        .attr('text-anchor', 'end')
        .attr('transform', 'translate(20, 0)');
}

Fiddle

如果标签是

3 or more patients

我试图让每个单词在单独的行中心对齐。

3 
or 
more 
patients

1 个答案:

答案 0 :(得分:2)

这是wrap function 的快速重构。您可以使它更简单,因为您想要分割每个单词(而不是宽度)。 但是围绕弧线安排会更复杂一些

function wrap(text) {
  text.each(function(d) {
    var text = d3.select(this),
        words = text.text().split(/\s+/).reverse(),
        lineNumber = 0,
        lineHeight = 1.1;
    // null out text
    text.text(null);
    // loop the words
    while (word = words.pop()) {
      // build tspan
      var tspan = text.append("tspan").attr("dy", ++lineNumber * lineHeight + "em").text(word);
      // adjust position based on angle
      if ((d.startAngle+d.endAngle)/2 < Math.PI ) {
        tspan.attr('x', 5)
      } else {
        tspan.attr('x', -25)
      }
      if ((d.startAngle+d.endAngle)/2 < Math.PI ) {
        tspan.attr('y', 0)
      } else {
        tspan.attr('y', -20)
      }
    }
  });
}

更新了fiddle