D3 V4条向下钻取-当x值为0时x轴刻度值重叠问题

问题描述

在这里,我正在使用d3 v4 bar drill-down chart的示例。在该示例中,它使用“ size”属性来构建向下钻取,但是我使用了它的children.length。向下钻取也相应地起作用,但是当子代长度小于10时,x轴刻度值显示为十进制值。为了避免x轴刻度的十进制值,我使用了以下代码:

var xAxis = d3.axisTop()
.scale(x)
.tickFormat(d3.format("d"))
.tickValues([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]);

但是使用上述代码后,当出现0值时,x轴刻度值将重叠,如下面的屏幕截图所示。

enter image description here

如何避免重叠的问题

var overallJson = {
  "name": "sisoc","children": [{
    "organisation_id": "4","name": "orgname4","children": []
  },{
    "organisation_id": "5","name": "org5","children": [{
      "aptcomplex_id": "4","name": "apt43","children": [{
        "building_id": "3","name": "bldg3","children": [{
          "floor_id": "flr_07","name": "flr_07","children": []
        }]
      },{
        "building_id": "blg_10","name": "bld_10","children": [{
          "floor_id": "5","name": "5_floor","children": []
        },{
          "floor_id": "flr_0700","name": "flr_0700","children": [{
            "unit_id": 4,"name": "testunit","user_id": 48,"username": "test111_test","children": [{
              "device_id": "test12","name": "TestMeter_2","serial": "1200000023C0123C"
            },{
              "device_id": "TestMeter_1","name": "TestMeter1","serial": "100000012C120202"
            }]
          }]
        },{
          "floor_id": "flr_09","name": "flr_09","children": [{
            "unit_id": 1,"name": "demouser_unit_10","user_id": 36,"username": "demouser","children": [{
              "device_id": "demo-meter-vc","name": "Demo Meter","serial": "10000000C9640011"
            }]
          },{
            "unit_id": 3,"name": "unit_50","user_id": 37,"username": "stagingtest","children": []
          }]
        },{
          "floor_id": "testfloor_!4","name": "testfloor_!4_up","children": []
        }]
      }]
    }]
  },{
    "organisation_id": "6","name": "org6",{
    "organisation_id": "7","name": "org7","children": [{
      "aptcomplex_id": "3","name": "apt3_update","children": [{
        "building_id": "1","name": "bldg1_update","children": []
      }]
    }]
  },{
    "organisation_id": "8","name": "org8_0","children": [{
      "aptcomplex_id": "APT_67","name": "Amritam","children": []
    }]
  },{
    "organisation_id": "org_109","name": "org_109","children": []
  }]
};

var margin = {
    top: 30,right: 120,bottom: 0,left: 120
  },width = 960 - margin.left - margin.right,height = 500 - margin.top - margin.bottom;

var x = d3.scaleLinear()
  .range([0,width]);

var barHeight = 20;

//var color = d3.scaleOrdinal()
//.range(["steelblue","#ccc"]);
var color = d3.scaleOrdinal(d3.schemeCategory20)

var duration = 750,delay = 25;

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

var xAxis = d3.axisTop()
  .scale(x)
  .tickFormat(d3.format("d"))
  .tickValues([0,20]);

var svg = d3.select("#barchartContainer").append("svg")
  .attr("width",width + margin.left + margin.right)
  .attr("height",height + margin.top + margin.bottom)
  .append("g")
  .attr("transform","translate(" + margin.left + "," + margin.top + ")");

svg.append("rect")
  .attr("class","background")
  .attr("width",width)
  .attr("height",height)
  .on("click",up);

svg.append("g")
  .attr("class","x axis");

svg.append("g")
  .attr("class","y axis")
  .append("line")
  .attr("y1","100%");

var chart_title = svg.append("text")
  .attr("x",(width / 2))
  .attr("y",0 - (margin.top / 2))
  .attr("id","chart_title")
  .attr("text-anchor","middle")
  .style("font-size","16px")
  .style("margin-bottom","50px")
  .style("text-decoration","underline")
  .text("Organisation Level");

d3.json("https://gist.githubusercontent.com/gallowayevan/f87b0911dcde85a5ccd3499a36e328e9/raw/a99e2ac89cff8255e3ae1f33f35ca01783c91139/readme.json",function(error,root) {
  root = overallJson;
  if (error) throw error;
  root = d3.hierarchy(root)
    .sum(d => d.size)
    .sort((a,b) => b.value - a.value);

  partition(root);

  x.domain([0,root.value,function(d) {
    console.log(d.data)
    return 0;
  }]).nice();

  down(root,0);
  chart_title.text("Organisation Level")
});

function down(d,i) {
  if (!d.children || this.__transition__) return;
  var end = duration + d.children.length * delay;

  // Mark any currently-displayed bars as exiting.
  var exit = svg.selectAll(".enter")
    .attr("class","exit");

  // Entering nodes immediately obscure the clicked-on bar,so hide it.
  exit.selectAll("rect").filter(function(p) {
      return p === d;
    })
    .style("fill-opacity",1e-6);

  // Enter the new bars for the clicked-on data.
  // Per above,entering bars are immediately visible.
  var enter = bar(d)
    .attr("transform",stack(i))
    .style("opacity",1);

  // Have the text fade-in,even though the bars are visible.
  // Color the bars as parents; they will fade to children if appropriate.
  enter.select("text").style("fill-opacity",1e-6);
  //enter.select("rect").style("fill",color(true));
  enter.select("rect").attr("fill",function(d,i) {
    return color(i);
  })

  // Update the x-scale domain.
  x.domain([0,d3.max(d.children,function(d) {
    //console.log(d.data);
    if (d.data.organisation_id) {

      chart_title.text("Organisation Level")
    }
    if (d.data.aptcomplex_id) {
      chart_title.text("Apartment Level")
    } else if (d.data.building_id) {
      chart_title.text("Building Level")
    } else if (d.data.floor_id) {
      chart_title.text("Floor Level")
    } else if (d.data.unit_id) {
      chart_title.text("Unit Level")
    } else if (d.data.device_id) {
      chart_title.text("Device Level")
    }

    if (d.height != 0) {
      return d.children.length;
    } else {
      return 0;
    }

  })]).nice();

  // Update the x-axis.
  svg.selectAll(".x.axis").transition()
    .duration(duration)
    .call(xAxis);

  // Transition entering bars to their new position.
  var enterTransition = enter.transition()
    .duration(duration)
    .delay(function(d,i) {
      return i * delay;
    })
    .attr("transform",i) {
      return "translate(0," + barHeight * i * 1.2 + ")";
    });

  // Transition entering text.
  enterTransition.select("text")
    .style("fill-opacity",1);

  // Transition entering rects to the new x-scale.
  enterTransition.select("rect")
    .attr("width",function(d) {
      if (d.height != 0) {

        return x(d.children.length);
      } else {
        return x(0)
      }

    })
    //.style("fill",function(d) { return color(!!d.children); });
    .attr("fill",i) {
      return color(i);
    })

  // Transition exiting bars to fade out.
  var exitTransition = exit.transition()
    .duration(duration)
    .style("opacity",1e-6)
    .remove();

  // Transition exiting bars to the new x-scale.
  exitTransition.selectAll("rect")
    .attr("width",function(d) {
      if (d.height != 0) {

        return x(d.children.length);
      } else {
        return x(0)
      }
    });

  // Rebind the current node to the background.
  svg.select(".background")
    .datum(d)
    .transition()
    .duration(end);

  d.index = i;
}

function up(d) {
  if (!d.parent || this.__transition__) return;
  var end = duration + d.children.length * delay;

  // Mark any currently-displayed bars as exiting.
  var exit = svg.selectAll(".enter")
    .attr("class","exit");

  // Enter the new bars for the clicked-on data's parent.
  var enter = bar(d.parent)
    .attr("transform"," + barHeight * i * 1.2 + ")";
    })
    .style("opacity",1e-6);

  // Color the bars as appropriate.
  // Exiting nodes will obscure the parent bar,so hide it.
  enter.select("rect")
    //.style("fill",function(d) { return color(!!d.children); })
    .attr("fill",i) {
      return color(i);
    })
    .filter(function(p) {
      return p === d;
    })
    .style("fill-opacity",1e-6);

  // Update the x-scale domain.
  x.domain([0,d3.max(d.parent.children,function(d) {
    //console.log(d.height)
    if (d.data.organisation_id) {
      chart_title.text("Organisation Level")
    }
    if (d.data.aptcomplex_id) {
      chart_title.text("Apartment Level")
    } else if (d.data.building_id) {
      chart_title.text("Building Level")
    } else if (d.data.floor_id) {
      chart_title.text("Floor Level")
    } else if (d.data.unit_id) {
      chart_title.text("Unit Level")
    } else if (d.data.device_id) {
      chart_title.text("Device Level")
    }
    if (d.height != 0) {
      return d.children.length;
    } else {
      return 0;
    }
  })]).nice();

  // Update the x-axis.
  svg.selectAll(".x.axis").transition()
    .duration(duration)
    .call(xAxis);

  // Transition entering bars to fade in over the full duration.
  var enterTransition = enter.transition()
    .duration(end)
    .style("opacity",1);

  // Transition entering rects to the new x-scale.
  // When the entering parent rect is done,make it visible!
  enterTransition.select("rect")
    .attr("width",function(d) {
      if (d.height != 0) {
        return x(d.children.length);
      } else {
        return x(0);
      }
    })
    .on("end",function(p) {
      if (p === d) d3.select(this).style("fill-opacity",null);
    });

  // Transition exiting bars to the parent's position.
  var exitTransition = exit.selectAll("g").transition()
    .duration(duration)
    .delay(function(d,stack(d.index));

  // Transition exiting text to fade out.
  exitTransition.select("text")
    .style("fill-opacity",1e-6);

  // Transition exiting rects to the new scale and fade to parent color.
  exitTransition.select("rect")
    .attr("width",function(d) {
      if (d.height != 0) {
        return x(d.children.length);
      } else {
        return x(0);
      }
    })
    //.style("fill",color(true));
    .attr("fill",i) {
      return color(i);
    })

  // Remove exiting nodes when the last child has finished transitioning.
  exit.transition()
    .duration(end)
    .remove();

  // Rebind the current parent to the background.
  svg.select(".background")
    .datum(d.parent)
    .transition()
    .duration(end);
}

// Creates a set of bars for the given data node,at the specified index.
function bar(d) {

  var bar = svg.insert("g",".y.axis")
    .attr("class","enter")
    .attr("transform","translate(0,5)")
    .selectAll("g")
    .data(d.children)
    .enter().append("g")
    .style("cursor",function(d) {
      return !d.children ? null : "pointer";
    })
    .on("click",down);

  bar.append("text")
    .attr("x",-6)
    .attr("y",barHeight / 2)
    .attr("dy",".35em")
    .style("text-anchor","end")
    .text(function(d) {
      return d.data.name;
    });

  bar.append("rect")
    .attr("width",function(d) {
      return x(d.value);
    })
    .attr("height",barHeight)
    .on("mousemove",function(d) {
      tooltip
        .style("left",d3.event.pageX - 50 + "px")
        .style("top",d3.event.pageY - 70 + "px")
        .style("display","inline-block")
        .html(d.data.name);
    })
    .on("mouseout",function(d) {
      tooltip.style("display","none");
    });


  return bar;
}

// A stateful closure for stacking bars horizontally.
function stack(i) {
  var x0 = 0;
  return function(d) {
    var tx = "translate(" + x0 + "," + barHeight * i * 1.2 + ")";
    x0 += x(d.value);
    return tx;
  };
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<div id="barchartContainer"></div>

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...