2017-11-20 8 views
5

ラベルが重ならないように配置する方法を理解しようとしています。ここでは、本当に小さな値で、見ることができるようにチャートd3 v4ドーナツチャートに小さな値で重なっているテキストとポーリングがある

enter image description here

の絵があり、テキストラベルが重複しています。私は各テキスト要素を繰り返し処理し、その位置を変更しようとしましたが、それは機能していないようです。この関数の最後で、各テキスト要素の位置を取得してから変更しようとしました。私は間違って何をしていますか?私は何時間もそれをしてきました。

_renderDonutChart() { 
    let self = this; 
    // console.log("Donut Chart is beginning render") 
    let textOffset = 14; 
    self.graph.data[0].forEach(function (d) { 
     d.value = +d.value; 
    }) 
    console.log(self.graph.data[0]) 
    let boxSize = (self.options.radius + self.options.padding) * 2; 
    let parent = d3.select(self.ui.parent); 
    //let color = d3.scaleOrdinal(['#dc8710', '#9e3400', '#f19b12']); 
    let color = d3.scaleOrdinal(d3.schemeCategory20c); 
    let svg = parent.append('svg') 
     .attr('width', boxSize * 2) 
     .attr('height', boxSize) 
     .attr('transform', 'translate(-111,0)') 
     .append('g') 
     .attr('transform', 'translate(' + boxSize + ',' + boxSize/2 + ')'); 
    svg.append('g') 
     .attr('class', 'slices') 
    svg.append("g") 
     .attr("class", "labelName") 
    svg.append("g") 
     .attr("class", "labelValue") 
    svg.append("g") 
     .attr("class", "lines") 
    svg.append("div") 
     .attr("class", "progress-circle__box progress-circle__box--victorytype") 
    let arc = d3.arc() 
     .innerRadius(self.options.radius - self.options.border) 
     .outerRadius(self.options.radius); 
    let outerArc = d3.arc() 
     .innerRadius((self.options.radius - self.options.border) * 1.2) 
     .outerRadius((self.options.radius) * 1.2); 
    let legendRectSize = self.options.radius * 0.05; 
    let legendSpacing = self.options.radius * 0.02; 
    let pie = d3.pie() 
     .value(function(d) { return d.value; }) 
     .sort(null); 
    let slice = svg.select('.slices') 
     .selectAll('path.slice') 
     .data(pie(self.graph.data[0])) 
     .enter() 
     .append('path') 
     .attr("class", "slice") 
     .attr('d', arc) 
     .attr('fill', function(d, i) { 
      return color(d.data.label); 
     }) 
     .transition().duration(1000) 
     .attrTween("d", function(d) { 
      this._current = this._current || 0; 
      var interpolate = d3.interpolate(this._current, d); 
      this._current = interpolate(0); 
      return function(t) { 
       return arc(interpolate(t)); 
      }; 
     }) 

    function midAngle(d){ 
     return d.startAngle + (d.endAngle - d.startAngle)/2; 
    } 
    let text = svg.select(".labelName").selectAll("text") 
     .data(pie(self.graph.data[0])) 
     .enter() 
     .append("text") 
     .attr('class', 'label') 
     .attr("dy", ".35em") 
     .attr('transform', function(d) { 

      // effectively computes the centre of the slice. 
      // see https://github.com/d3/d3-shape/blob/master/README.md#arc_centroid 
      var pos = outerArc.centroid(d); 

      // changes the point to be on left or right depending on where label is. 
      pos[0] = self.options.radius * 0.97 * (midAngle(d) < Math.PI ? 1 : -1); 
      return 'translate(' + pos + ')'; 
     }) 
     .style('text-anchor', function(d) { 
      // if slice centre is on the left, anchor text to start, otherwise anchor to end 
      return (midAngle(d)) < Math.PI ? 'start' : 'end'; 
     }) 
     .style("fill", "white") 
     .text(function(d) { 
      return (" " + d.data.label+": " +d.value+""); 
     }) 
     .transition().duration(1000) 
     .attrTween("transform", function(d) { 
      this._current = this._current || d; 
      var interpolate = d3.interpolate(this._current, d); 
      this._current = interpolate(0); 
      return function(t) { 
       var d2 = interpolate(t); 
       var pos = outerArc.centroid(d2); 
       pos[0] = self.options.radius * (midAngle(d2) < Math.PI ? 1 : -1); 
       return "translate("+ pos +")"; 
      }; 
     }) 
     .styleTween("text-anchor", function(d){ 
      this._current = this._current || d; 
      var interpolate = d3.interpolate(this._current, d); 
      this._current = interpolate(0); 
      return function(t) { 
       var d2 = interpolate(t); 
       return midAngle(d2) < Math.PI ? "start":"end"; 
      }; 
     }) 
     .text(function(d) { 
      return (d.data.label+": "+d.value+"%"); 
     }) 
    let polyline = svg.select(".lines").selectAll("polyline") 
     .data(pie(self.graph.data[0])) 
     .enter() 
     .append("polyline") 
     .attr('points', function(d) { 
      var pos = outerArc.centroid(d); 
      pos[0] = self.options.radius * 0.95 * (midAngle(d) < Math.PI ? 1 : -1); 
      return [arc.centroid(d), outerArc.centroid(d), pos] 
     }) 
     .style("fill", "none") 
     .style("stroke", "white") 
     .style("stroke-width", "1px"); 

    let prev; 
    text.each(function(d, i) { 
     if(i > 0) { 
      let thisbb = this.getBoundingClientRect(), 
       prevbb = prev.getBoundingClientRect(); 
      // move if they overlap 
      console.log(thisbb.left); 
      console.log(prevbb.right); 
      if(!(thisbb.right < prevbb.left || 
       thisbb.left > prevbb.right || 
       thisbb.bottom < prevbb.top || 
       thisbb.top > prevbb.bottom)) { 
       var ctx = thisbb.left + (thisbb.right - thisbb.left)/2, 
        cty = thisbb.top + (thisbb.bottom - thisbb.top)/2, 
        cpx = prevbb.left + (prevbb.right - prevbb.left)/2, 
        cpy = prevbb.top + (prevbb.bottom - prevbb.top)/2, 
        off = Math.sqrt(Math.pow(ctx - cpx, 2) + Math.pow(cty - cpy, 2))/2; 
       d3.select(this).attr("transform", 
        "translate(" + Math.cos(((d.startAngle + d.endAngle - Math.PI)/2)) * 
        (self.options.radius + textOffset + off) + "," + 
        Math.sin((d.startAngle + d.endAngle - Math.PI)/2) * 
        (self.options.radius + textOffset + off) + ")"); 
      } 
     } 
     prev = this; 
    }); 

    // console.log("Donut Chart is ending render") 
} 
+0

チャートにこのコードの構造を追加しようとした場合ディバインマージンは、あなたが角度の関数に基づいて、異なる 'dy'値を与えることができます:'機能(d){return d.endAngle - d.startAngle> .02? .35:.7; } '? –

+0

私はこれを見たことがありますか?https://www.safaribooksonline.com/blog/2014/03/11/solving-d3-label-placement-constraint-relaxing/ – Cyril

答えて

0

私は同じ問題がありました。私の最善の解決策は、Svg領域のサイズを現在のウィンドウに基づいて増やし、ドーナツの半径に基づいて伝説にパディングを追加することでした。

すなわち:項目数が高くなりすぎまで

var margin = {top: 20, right: 100, bottom: 30, left: 40}; 
    var svgWidth = window.innerWidth - (window.innerWidth/4); 
    var width = svgWidth, 
     height = (Math.min(width)/2) + 100, 
     radius = Math.min(width, height)/3; 

    var legendRectSize = (radius * 0.08); 
    var legendSpacing = (radius * 0.05); 

これは私のために働きました。私はスライス/アークホバーイベントの中心に表示するために、縁の周りのラベルから修正しました。 (彼らは、このスナップショットに傾斜している理由であるデータ値、上のアニメーションがあります)

D3 Donut Chart Amended labels

私はこれが読めないデータラベルがあまり混乱したと思いました。

0

thisと同じ問題があった場合、円グラフのセグメントに余裕を持たせ、円を3%の値に戻し、線でテキストを描画し、別のものに積み重ねる必要があります。 Y +マージン

if(percent<3){ 
     o[1] 
     pos[1] += i*15 
     } 
     //return [label.centroid(d),[o[0],0[1]] , pos]; 
     return [label.centroid(d),[o[0],pos[1]] , pos]; 
     }) 

とその値< 3ドローテキストは

関連する問題