javascript - d3js 在多行上写标签

标签 javascript d3.js charts

我正在研究图形,并且在图表方面遇到了一些困难。我想绘制饼图(或 donut )并以两行或更多行显示标签,以便为图表获得更多空间。

这是我的代码

var dataGroupPotential = [];
var pieGroup;
var svg;

processData("pieGPChart");

function processData(chartDivId) {
  $("#pieGPLegend").text("Title : myTitle");

  //Construction du tableau data

  dataGroupPotential.push({
    label: "long text 1 : 100 000 000",
    value: 100000000
  });
  dataGroupPotential.push({
    label: "long text 2 : 200 000 000",
    value: 200000000
  });
  dataGroupPotential.push({
    label: "long text 3 : 300 000 000",
    value: 300000000
  });


  var width = $("#" + chartDivId).width();
  var dividor = 2.75;
  var height = width / dividor;

  //Ajout des éléments svg pour tracer le graphique
  svg = d3.select("#" + chartDivId).append("svg")
    .attr("width", '100%')
    .attr("height", '100%')
    .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
    .attr('preserveAspectRatio', 'xMinYMin')
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");;

  svg.append("g").attr("class", "slices");
  svg.append("g").attr("class", "labels");
  svg.append("g").attr("class", "lines");

  $("#" + chartDivId).height(height);

  drawMyPie(svg, dataGroupPotential, width, height);

  window.addEventListener('resize', function(event) {
    // do stuff here
    var chartDivId = "pieGPChart";
    var width = $("#" + chartDivId).width();
    var dividor = 2.75;
    var height = width / dividor;
    $("#" + chartDivId).height(height);

    drawMyPie(svg, dataGroupPotential, width, height);
  });
}



function drawMyPie(svg, data, width, height) {
  var radius = Math.min(width, height) / 2;

  var pie = d3.pie()
    .sort(null)
    .value(function(d) {
      return d.value;
    });

  var arc = d3.arc()
    .outerRadius(radius * 0.8)
    .innerRadius(radius * 0.4);

  var outerArc = d3.arc()
    .innerRadius(radius * 0.9)
    .outerRadius(radius * 0.9);

  //svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

  var key = function(d) {
    return d.data.label;
  };

  var color = d3.scaleOrdinal(d3.schemeCategory20);
  change(data);

  function mergeWithFirstEqualZero(first, second) {
    var secondSet = d3.set();
    second.forEach(function(d) {
      secondSet.add(d.label);
    });

    var onlyFirst = first
      .filter(function(d) {
        return !secondSet.has(d.label)
      })
      .map(function(d) {
        return {
          label: d.label,
          value: 0
        };
      });
    return d3.merge([second, onlyFirst])
      .sort(function(a, b) {
        return d3.ascending(a.label, b.label);
      });
  }

  function change(data) {
    var duration = 3000;
    var data0 = svg.select(".slices").selectAll("path.slice")
      .data().map(function(d) {
        return d.data
      });
    if (data0.length == 0) data0 = data;
    var was = mergeWithFirstEqualZero(data, data0);
    var is = mergeWithFirstEqualZero(data0, data);

    /* ------- SLICE ARCS -------*/

    var slice = svg.select(".slices").selectAll("path.slice")
      .data(pie(was), key);

    slice.enter()
      .insert("path")
      .attr("class", "slice")
      .style("fill", function(d) {
        return color(d.data.label);
      })
      .each(function(d) {
        this._current = d;
      });

    slice = svg.select(".slices").selectAll("path.slice")
      .data(pie(is), key);

    slice
      .transition().duration(duration)
      .attrTween("d", function(d) {
        var interpolate = d3.interpolate(this._current, d);
        var _this = this;
        return function(t) {
          _this._current = interpolate(t);
          return arc(_this._current);
        };
      });

    slice = svg.select(".slices").selectAll("path.slice")
      .data(pie(data), key);

    slice
      .exit().transition().delay(duration).duration(0)
      .remove();

    /* ------- TEXT LABELS -------*/

    var text = svg.select(".labels").selectAll("text")
      .data(pie(was), key);

    text.enter()
      .append("text")
      .attr("dy", ".35em")
      .style("opacity", 0)
      .text(function(d) {
        return d.data.label;
      })
      .each(function(d) {
        this._current = d;
      });

    //var legend = text.enter();

    //text.append("text")
    //    .attr("dy", "-10")
    //    .style("opacity", 0)
    //    .text(function (d) {
    //        return d.data.label;
    //    })
    //.each(function (d) {
    //    this._current = d;
    //});
    //text.append("text")
    //    .attr("dy", "10")
    //    .style("opacity", 0)
    //    .text(function (d) {
    //        return d.data.label;
    //    })
    //.each(function (d) {
    //    this._current = d;
    //});

    function midAngle(d) {
      return d.startAngle + (d.endAngle - d.startAngle) / 2;
    }

    text = svg.select(".labels").selectAll("text")
      .data(pie(is), key);

    text.transition().duration(duration)
      .style("opacity", function(d) {
        return d.data.value == 0 ? 0 : 1;
      })
      .attrTween("transform", function(d) {
        var interpolate = d3.interpolate(this._current, d);
        var _this = this;
        return function(t) {
          var d2 = interpolate(t);
          _this._current = d2;
          var pos = outerArc.centroid(d2);
          pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
          return "translate(" + pos + ")";
        };
      })
      .styleTween("text-anchor", function(d) {
        var interpolate = d3.interpolate(this._current, d);
        return function(t) {
          var d2 = interpolate(t);
          return midAngle(d2) < Math.PI ? "start" : "end";
        };
      });

    text = svg.select(".labels").selectAll("text")
      .data(pie(data), key);

    text
      .exit().transition().delay(duration)
      .remove();

    /* ------- SLICE TO TEXT POLYLINES -------*/

    var polyline = svg.select(".lines").selectAll("polyline")
      .data(pie(was), key);

    polyline.enter()
      .append("polyline")
      .style("opacity", 0)
      .each(function(d) {
        this._current = d;
      });

    polyline = svg.select(".lines").selectAll("polyline")
      .data(pie(is), key);

    polyline.transition().duration(duration)
      .style("opacity", function(d) {
        return d.data.value == 0 ? 0 : .5;
      })
      .attrTween("points", function(d) {
        this._current = this._current;
        var interpolate = d3.interpolate(this._current, d);
        var _this = this;
        return function(t) {
          var d2 = interpolate(t);
          _this._current = d2;
          var pos = outerArc.centroid(d2);
          pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
          return [arc.centroid(d2), outerArc.centroid(d2), pos];
        };
      });

    polyline = svg.select(".lines").selectAll("polyline")
      .data(pie(data), key);

    polyline
      .exit().transition().delay(duration)
      .remove();
  };
}
    svg {
        width: 100%;
        height: 100%;
    }

    path.slice {
        stroke-width: 2px;
    }

    polyline {
        opacity: .3;
        stroke: black;
        stroke-width: 2px;
        fill: none;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.js"></script>


<div class="panel panel-default">
  <div class="panel-body">
    <div style="text-align:center;" class="row">
      <h4 id="pieGPLegend"></h4>
      <div id="pieGPChart"></div>
    </div>
  </div>
</div>

对于标签,我想要类似的东西

long text 1
100 000 000

我已经尝试过一些东西,但没有成功。这是我尝试过的,但我仍然对 d3js 感到困惑

var legend = text.enter();

text.append("text")
    .attr("dy", "-10")
    .style("opacity", 0)
    .text(function (d) {
        return d.data.label;
    })
.each(function (d) {
    this._current = d;
});
text.append("text")
    .attr("dy", "10")
    .style("opacity", 0)
    .text(function (d) {
        return d.data.label;
    })
.each(function (d) {
    this._current = d;
});

欢迎任何帮助、建议、评论!谢谢

达米安

最佳答案

如果您希望始终在冒号后中断文本,最简单的方法是使用 <tspan> :

.append("tspan")
.attr("x", 0)
.attr("dy", "1.3em")
.text(function(d) {
    return d.data.label.split(":")[1];
})

这是经过更改的代码:

var dataGroupPotential = [];
var pieGroup;
var svg;

processData("pieGPChart");

function processData(chartDivId) {
  $("#pieGPLegend").text("Title : myTitle");

  //Construction du tableau data

  dataGroupPotential.push({
    label: "long text 1 : 100 000 000",
    value: 100000000
  });
  dataGroupPotential.push({
    label: "long text 2 : 200 000 000",
    value: 200000000
  });
  dataGroupPotential.push({
    label: "long text 3 : 300 000 000",
    value: 300000000
  });


  var width = $("#" + chartDivId).width();
  var dividor = 2.75;
  var height = width / dividor;

  //Ajout des éléments svg pour tracer le graphique
  svg = d3.select("#" + chartDivId).append("svg")
    .attr("width", '100%')
    .attr("height", '100%')
    .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
    .attr('preserveAspectRatio', 'xMinYMin')
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");;

  svg.append("g").attr("class", "slices");
  svg.append("g").attr("class", "labels");
  svg.append("g").attr("class", "lines");

  $("#" + chartDivId).height(height);

  drawMyPie(svg, dataGroupPotential, width, height);

  window.addEventListener('resize', function(event) {
    // do stuff here
    var chartDivId = "pieGPChart";
    var width = $("#" + chartDivId).width();
    var dividor = 2.75;
    var height = width / dividor;
    $("#" + chartDivId).height(height);

    drawMyPie(svg, dataGroupPotential, width, height);
  });
}



function drawMyPie(svg, data, width, height) {
  var radius = Math.min(width, height) / 2;

  var pie = d3.pie()
    .sort(null)
    .value(function(d) {
      return d.value;
    });

  var arc = d3.arc()
    .outerRadius(radius * 0.8)
    .innerRadius(radius * 0.4);

  var outerArc = d3.arc()
    .innerRadius(radius * 0.9)
    .outerRadius(radius * 0.9);

  //svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

  var key = function(d) {
    return d.data.label;
  };

  var color = d3.scaleOrdinal(d3.schemeCategory20);
  change(data);

  function mergeWithFirstEqualZero(first, second) {
    var secondSet = d3.set();
    second.forEach(function(d) {
      secondSet.add(d.label);
    });

    var onlyFirst = first
      .filter(function(d) {
        return !secondSet.has(d.label)
      })
      .map(function(d) {
        return {
          label: d.label,
          value: 0
        };
      });
    return d3.merge([second, onlyFirst])
      .sort(function(a, b) {
        return d3.ascending(a.label, b.label);
      });
  }

  function change(data) {
    var duration = 3000;
    var data0 = svg.select(".slices").selectAll("path.slice")
      .data().map(function(d) {
        return d.data
      });
    if (data0.length == 0) data0 = data;
    var was = mergeWithFirstEqualZero(data, data0);
    var is = mergeWithFirstEqualZero(data0, data);

    /* ------- SLICE ARCS -------*/

    var slice = svg.select(".slices").selectAll("path.slice")
      .data(pie(was), key);

    slice.enter()
      .insert("path")
      .attr("class", "slice")
      .style("fill", function(d) {
        return color(d.data.label);
      })
      .each(function(d) {
        this._current = d;
      });

    slice = svg.select(".slices").selectAll("path.slice")
      .data(pie(is), key);

    slice
      .transition().duration(duration)
      .attrTween("d", function(d) {
        var interpolate = d3.interpolate(this._current, d);
        var _this = this;
        return function(t) {
          _this._current = interpolate(t);
          return arc(_this._current);
        };
      });

    slice = svg.select(".slices").selectAll("path.slice")
      .data(pie(data), key);

    slice
      .exit().transition().delay(duration).duration(0)
      .remove();

    /* ------- TEXT LABELS -------*/

    var text = svg.select(".labels").selectAll("text")
      .data(pie(was), key);

    text.enter()
      .append("text")
      .attr("dy", ".35em")
      .style("opacity", 0)
      .text(function(d) {
        return d.data.label.split(":")[0] + ":";
      })
      .each(function(d) {
        this._current = d;
      })
      .append("tspan")
      .attr("x", 0)
      .attr("dy", "1.3em")
      .text(function(d) {
        return d.data.label.split(":")[1];
      })
      .each(function(d) {
        this._current = d;
      });

    //var legend = text.enter();

    //text.append("text")
    //    .attr("dy", "-10")
    //    .style("opacity", 0)
    //    .text(function (d) {
    //        return d.data.label;
    //    })
    //.each(function (d) {
    //    this._current = d;
    //});
    //text.append("text")
    //    .attr("dy", "10")
    //    .style("opacity", 0)
    //    .text(function (d) {
    //        return d.data.label;
    //    })
    //.each(function (d) {
    //    this._current = d;
    //});

    function midAngle(d) {
      return d.startAngle + (d.endAngle - d.startAngle) / 2;
    }

    text = svg.select(".labels").selectAll("text")
      .data(pie(is), key);

    text.transition().duration(duration)
      .style("opacity", function(d) {
        return d.data.value == 0 ? 0 : 1;
      })
      .attrTween("transform", function(d) {
        var interpolate = d3.interpolate(this._current, d);
        var _this = this;
        return function(t) {
          var d2 = interpolate(t);
          _this._current = d2;
          var pos = outerArc.centroid(d2);
          pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
          return "translate(" + pos + ")";
        };
      })
      .styleTween("text-anchor", function(d) {
        var interpolate = d3.interpolate(this._current, d);
        return function(t) {
          var d2 = interpolate(t);
          return midAngle(d2) < Math.PI ? "start" : "end";
        };
      });

    text = svg.select(".labels").selectAll("text")
      .data(pie(data), key);

    text
      .exit().transition().delay(duration)
      .remove();

    /* ------- SLICE TO TEXT POLYLINES -------*/

    var polyline = svg.select(".lines").selectAll("polyline")
      .data(pie(was), key);

    polyline.enter()
      .append("polyline")
      .style("opacity", 0)
      .each(function(d) {
        this._current = d;
      });

    polyline = svg.select(".lines").selectAll("polyline")
      .data(pie(is), key);

    polyline.transition().duration(duration)
      .style("opacity", function(d) {
        return d.data.value == 0 ? 0 : .5;
      })
      .attrTween("points", function(d) {
        this._current = this._current;
        var interpolate = d3.interpolate(this._current, d);
        var _this = this;
        return function(t) {
          var d2 = interpolate(t);
          _this._current = d2;
          var pos = outerArc.centroid(d2);
          pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
          return [arc.centroid(d2), outerArc.centroid(d2), pos];
        };
      });

    polyline = svg.select(".lines").selectAll("polyline")
      .data(pie(data), key);

    polyline
      .exit().transition().delay(duration)
      .remove();
  };
}
svg {
        width: 100%;
        height: 100%;
    }

    path.slice {
        stroke-width: 2px;
    }

    polyline {
        opacity: .3;
        stroke: black;
        stroke-width: 2px;
        fill: none;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.js"></script>


<div class="panel panel-default">
  <div class="panel-body">
    <div style="text-align:center;" class="row">
      <h4 id="pieGPLegend"></h4>
      <div id="pieGPChart"></div>
    </div>
  </div>
</div>

关于javascript - d3js 在多行上写标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45953810/

相关文章:

javascript - Highcharts 轴悬停

javascript - 如何删除谷歌图表中的工具提示

javascript - 如何用鼠标拖放?

javascript - 当父级来自不同域时,使用 jQuery 在另一个 iframe 中执行 javascript 函数?

javascript - 使用 d3.js 显示数据

d3.js - d3js : make new parent data descend into child nodes

javascript - 谷歌图表对数刻度

不同浏览器中的 Javascript 滚动条类和鼠标滚轮速度

javascript - 在浏览器调整大小时调整内容 div + 图像

d3.js - 如何使用非树数据创建 d3.js 可折叠力布局?