动态调整自定义C3片段图图例大小(使用D3?)

玩技站长 科技常识评论64字数 8420阅读模式
摘要最佳答案:Data[i].reduce(function(pv;legendData.forEach(function(el:.1%“)(el.ratio)].join(‘:dat...
提问开始:

我添加了一个使用名称、值和比率的自定义图例到C3片段图中。文章源自玩技e族-https://www.playezu.com/748443.html

目前使用固定宽度进行定位。有没有一种聪明的方法,比如使用D3,来动态计算图例行的像素宽度?文章源自玩技e族-https://www.playezu.com/748443.html

文章源自玩技e族-https://www.playezu.com/748443.html

var columns = ['data11', 'data2', 'data347', 'data40091'];
var data = [150, 250, 300, 50];
var colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B'];
var padding = 5;
var legendData = [];
var sumTotal = 0
//prepare pie data
var columnData = [];
var columnNames = {};
for (i = 0; i < columns.length; i++) {
  columnData.push([columns[i]].concat(data[i]));
  var val = (Array.isArray(data[i])) ? data[i].reduce(function(pv, cv) {
    return pv + cv;
  }, 0) : data[i];
  sumTotal += val;
  legendData.push({
    id: columns[i],
    value: val,
    ratio: 0.0
  });
}
legendData.forEach(function(el, i) {
  el.ratio = el.value / sumTotal
  columnNames[el.id] = [el.id, d3.format(",.0f")(el.value), d3.format(",.1%")(el.ratio)].join(';');
});
var chart = c3.generate({
  bindto: d3.select('#chart'),
  data: {
    columns: [
      [columns[0]].concat(data[0])
    ],
    names: columnNames,
    type: 'pie',
  },
  legend: {
    position: 'right',
    show: true
  },
  pie: {
    label: {
      threshold: 0.001,
      format: function(value, ratio, id) {
        return [id, d3.format(",.0f")(value), "[" + d3.format(",.1%")(ratio) + "]"].join(';');
      }
    }
  },
  color: {
    pattern: colors
  },
  onrendered: function() {
    redrawLabelBackgrounds();
    redrawLegend();
  }
});
function addLabelBackground(index) {
  //get label text element
  var textLabel = d3.select(".c3-target-" + columns[index] + " > text");
  //add rect to parent
  var labelNode = textLabel.node();
  if (labelNode /*&& labelNode.innerHTML.length > 0*/ ) {
    var p = d3.select(labelNode.parentNode).insert("rect", "text")
      .style("fill", colors[index]);
  }
}
for (var i = 0; i < columns.length; i++) {
  if (i > 0) {
    setTimeout(function(column) {
      chart.load({
        columns: [
          columnData
, ] }); //chart.data.names(columnNames
) addLabelBackground(column); }, (i * 5000 / columnData.length), i); } else { addLabelBackground(i); } } function redrawLegend() { d3.select('#chart').selectAll(".c3-legend-item > text").each(function(v) { // get d3 node var legendItem = d3.select(this); legendItem.attr("style", "font-size: 8pt;"); var legendItemNode = legendItem.node(); //check if label is drawn if (legendItemNode) { if (legendItemNode.childElementCount === 0 && legendItemNode.innerHTML.length > 0) { //build data var data = legendItemNode.innerHTML.split(';'); legendItem.text(""); // TODO: size the "rows" dynamically legendItem.append("tspan") .text(data[0] + ": ") .attr("class", "id-row") .attr("text-anchor", "start"); legendItem.append("tspan") .text(data[1] + " = ") .attr("class", "value-row") .attr("x", 170) .attr("text-anchor", "end"); legendItem.append("tspan") .text(data[2]) .attr("class", "ratio-row") .attr("x", 200) .attr("text-anchor", "end"); //.attr("transform", (n === 0) ? "translate(0,0)" : "translate(200,0)") } } }); d3.select('#chart').selectAll(".c3-legend-item > rect").each(function(v) { var legendItem = d3.select(this); legendItem.attr("width", 170); }); } function redrawLabelBackgrounds() { //for all label texts drawn yet d3.select('#chart').selectAll(".c3-chart-arc > text").each(function(v) { // get d3 node var label = d3.select(this); var labelNode = label.node(); //check if label is drawn if (labelNode) { if (labelNode.childElementCount === 0 && labelNode.innerHTML.length > 0) { //build data var data = labelNode.innerHTML.split(';'); label.text(""); data.forEach(function(i, n) { label.append("tspan") .text(i) .attr("dy", (n === 0) ? 0 : "1.2em") .attr("x", 0) .attr("text-anchor", "middle"); }, label); } //check if element is visible if (d3.select(labelNode.parentNode).style("display") !== 'none') { //get pos of the label text var pos = label.attr("transform").match(/-?d+(.d+)?/g); if (pos) { //get surrounding box of the label var bbox = labelNode.getBBox(); //now draw and move the rects d3.select(labelNode.parentNode).select("rect") .attr("transform", "translate(" + (pos[0] - (bbox.width + padding) / 2) + "," + (pos[1] - bbox.height / labelNode.childElementCount) + ")") .attr("width", bbox.width + padding) .attr("height", bbox.height + padding); } } } }); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.9/c3.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.9/c3.min.js"></script>
<div id="chart">
</div>

文章源自玩技e族-https://www.playezu.com/748443.html

这个问题基于我以前提出的关于自定义图例/标签重叠的问题:C3/D3 pie legend format / label overlap文章源自玩技e族-https://www.playezu.com/748443.html

回答开始:得票数 0文章源自玩技e族-https://www.playezu.com/748443.html

我想出了如何解决这个问题,尽管可能有更聪明的解决方案。我现在使用每个tspan节点的"getComputedTextLength“来计算最大值。文章源自玩技e族-https://www.playezu.com/748443.html

文章源自玩技e族-https://www.playezu.com/748443.html

var columns = ['data11', 'data2', 'data347', 'data40098'];
var data = [150, 250, 300, 50];
var colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B'];
var padding = 5;
var legendData = [];
var sumTotal = 0
//prepare pie data
var columnData = [];
var columnNames = {};
for (i = 0; i < columns.length; i++) {
  columnData.push([columns[i]].concat(data[i]));
  var val = (Array.isArray(data[i])) ? data[i].reduce(function(pv, cv) {
    return pv + cv;
  }, 0) : data[i];
  sumTotal += val;
  legendData.push({
    id: columns[i],
    value: val,
    ratio: 0.0
  });
}
legendData.forEach(function(el, i) {
  el.ratio = el.value / sumTotal
  columnNames[el.id] = [el.id, d3.format(",.0f")(el.value), d3.format(",.1%")(el.ratio)].join(';');
});
var chart = c3.generate({
  bindto: d3.select('#chart'),
  data: {
    columns: [
      [columns[0]].concat(data[0])
    ],
    names: columnNames,
    type: 'pie',
  },
  legend: {
    position: 'right',
    show: true
  },
  pie: {
    label: {
      threshold: 0.001,
      format: function(value, ratio, id) {
        return [id, d3.format(",.0f")(value), "[" + d3.format(",.1%")(ratio) + "]"].join(';');
      }
    }
  },
  color: {
    pattern: colors
  },
  onrendered: function() {
    redrawLabelBackgrounds();
    redrawLegend();
  }
});
function addLabelBackground(index) {
  //get label text element
  var textLabel = d3.select(".c3-target-" + columns[index] + " > text");
  //add rect to parent
  var labelNode = textLabel.node();
  if (labelNode /*&& labelNode.innerHTML.length > 0*/ ) {
    var p = d3.select(labelNode.parentNode).insert("rect", "text")
      .style("fill", colors[index]);
  }
}
for (var i = 0; i < columns.length; i++) {
  if (i > 0) {
    setTimeout(function(column) {
      chart.load({
        columns: [
          columnData
, ] }); //chart.data.names(columnNames
) addLabelBackground(column); }, (i * 5000 / columnData.length), i); } else { addLabelBackground(i); } } function redrawLegend() { var maxIdRowWidth = 0, maxValueRowWidth = 0, maxRatioRowWidth = 0; d3.select('#chart').selectAll(".c3-legend-item > text").each(function() { // get d3 node var legendItem = d3.select(this); var legendItemNode = legendItem.node(); //check if label is drawn if (legendItemNode) { if (legendItemNode.childElementCount === 0 && legendItemNode.innerHTML.length > 0) { //build data var data = legendItemNode.innerHTML.split(';'); legendItem.text(""); var idRowWidth = legendItem.append("tspan") .text(data[0] + ":") .attr("class", "id-row") .attr("text-anchor", "start") .node().getComputedTextLength(); maxIdRowWidth = Math.max(maxIdRowWidth, idRowWidth); var valueRowWidth = legendItem.append("tspan") .text(data[1] + " =") .attr("class", "value-row") .attr("text-anchor", "end") .node().getComputedTextLength(); maxValueRowWidth = Math.max(maxValueRowWidth, valueRowWidth); var ratioRowWidth = legendItem.append("tspan") .text(data[2]) .attr("class", "ratio-row") .attr("text-anchor", "end") .node().getComputedTextLength(); maxRatioRowWidth = Math.max(maxRatioRowWidth, ratioRowWidth); } } }); var xOffset = parseInt(d3.select('#chart').select(".c3-legend-item > text").attr("x")); var padding = 2; d3.select('#chart').selectAll(".id-row") .attr("width", Math.round(maxIdRowWidth)); d3.select('#chart').selectAll(".value-row") .attr("x", Math.round(maxValueRowWidth+maxIdRowWidth)+xOffset+padding) .attr("width", Math.round(maxValueRowWidth)); d3.select('#chart').selectAll(".ratio-row") .attr("x", Math.round(maxValueRowWidth+maxIdRowWidth+maxRatioRowWidth)+xOffset+2*padding) .attr("width", Math.round(maxRatioRowWidth)); d3.select('#chart').selectAll(".c3-legend-item > rect") .attr("width", Math.round(maxValueRowWidth+maxIdRowWidth+maxRatioRowWidth)); } function redrawLabelBackgrounds() { //for all label texts drawn yet d3.select('#chart').selectAll(".c3-chart-arc > text").each(function(v) { // get d3 node var label = d3.select(this); var labelNode = label.node(); //check if label is drawn if (labelNode) { if (labelNode.childElementCount === 0 && labelNode.innerHTML.length > 0) { //build data var data = labelNode.innerHTML.split(';'); label.text(""); data.forEach(function(i, n) { label.append("tspan") .text(i) .attr("dy", (n === 0) ? 0 : "1.2em") .attr("x", 0) .attr("text-anchor", "middle"); }, label); } //check if element is visible if (d3.select(labelNode.parentNode).style("display") !== 'none') { //get pos of the label text var pos = label.attr("transform").match(/-?d+(.d+)?/g); if (pos) { //get surrounding box of the label var bbox = labelNode.getBBox(); //now draw and move the rects d3.select(labelNode.parentNode).select("rect") .attr("transform", "translate(" + (pos[0] - (bbox.width + padding) / 2) + "," + (pos[1] - bbox.height / labelNode.childElementCount) + ")") .attr("width", bbox.width + padding) .attr("height", bbox.height + padding); } } } }); }
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.12/c3.min.css" rel="stylesheet" />
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.12/c3.min.js"></script>
<div id="chart">
</div>

文章源自玩技e族-https://www.playezu.com/748443.html

文章源自玩技e族-https://www.playezu.com/748443.html
玩技站长微信
添加好友自动发送入群邀请
weinxin
rainbow-shownow
玩技官方公众号
官方微信公众号
weinxin
PLAYEZU
 
匿名

发表评论

匿名网友
确定