如何在d3条形图中左对齐刻度

时间:2014-12-29 18:28:12

标签: javascript html css d3.js

我创建了一个堆积条形图 在y轴侧,我有不同长度的蜱。 我想要完成的是将刻度线中的文本对齐到左侧。 这是我的例子:http://jsfiddle.net/2khbceut/2/

html

<title>Diverging Stacked Bar Chart with D3.js</title>
<body>
    <div id="figure" align="center" style="margin-bottom: 50px;"></div>
</body>

的javascript

$(document).ready(getTopolegy());





function getTopolegy(){

      var data = null;
        var links = parseTopology(data);
        createChart(links);

}

function parseTopology(data){
  var links=[{1:5,2:5,3:10,N:20,link_name: "Link CHGIL21CRS-SFXCA21CRS"},
            {1:5,2:5,3:10,N:20,link_name: "Link NYCNY21CRS-NYCNY22CRS"}];

  return links;  
}

function jsonNameToId(name){
  switch (allocated_priority) {
  case "allocated_priority":
    return 1;
  case "allocated_default":
    return 2;
  case "spare_capacity":
    return 3;
  case "total":
    return "N";
  default:
    return 999;
  }
}

function createChart(data){
  var margin = {top: 50, right: 20, bottom: 10, left: 210},
    width = 1000 - margin.left - margin.right,
    height = 100 - margin.top - margin.bottom;

var y = d3.scale.ordinal()
    .rangeRoundBands([0, height], .3);

var x = d3.scale.linear()
    .rangeRound([0, width]);

var color = d3.scale.ordinal()
    .range(["#cccccc", "#92c6db", "#086fad"]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("top");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")

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

  color.domain(["Allocated Priority %", "Allocated Default %", "Spare Capacity %"]);


  // d3.csv("js/raw_data.csv", function(error, data) {

  data.forEach(function(d) {
    d["Allocated Priority %"] = +d[1]*100/d.N;
    d["Allocated Default %"] = +d[2]*100/d.N;
    d["Spare Capacity %"] = +d[3]*100/d.N;

    var x0 = 0;
    var idx = 0;
    d.boxes = color.domain().map(function(name) { return {name: name, x0: x0, x1: x0 += +d[name], N: +d.N, n: +d[idx += 1]}; });

  });

  var min_val = d3.min(data, function(d) {
          return d.boxes["0"].x0;
          });

  var max_val = d3.max(data, function(d) {
          return d.boxes["2"].x1;
          });

  x.domain([min_val, max_val]).nice();
  y.domain(data.map(function(d) { return d.link_name; }));

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

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)

  var vakken = svg.selectAll(".Link")
      .data(data)
    .enter().append("g")
      .attr("class", "bar")
      .attr("transform", function(d) { return "translate(0," + y(d.link_name) + ")"; });

  var bars = vakken.selectAll("rect")
      .data(function(d) { return d.boxes; })
    .enter().append("g").attr("class", "subbar");

  bars.append("rect")
      .attr("height", y.rangeBand())
      .attr("x", function(d) { return x(d.x0); })
      .attr("width", function(d) { return x(d.x1) - x(d.x0); })
      .style("fill", function(d) { return color(d.name); });

  bars.append("text")
      .attr("x", function(d) { return x(d.x0); })
      .attr("y", y.rangeBand()/2)
      .attr("dy", "0.5em")
      .attr("dx", "0.5em")
      .style("font" ,"10px sans-serif")
      .style("text-anchor", "begin")
      .text(function(d) { return d.n !== 0 && (d.x1-d.x0)>3 ? d.n : "" });

  vakken.insert("rect",":first-child")
      .attr("height", y.rangeBand())
      .attr("x", "1")
      .attr("width", width)
      .attr("fill-opacity", "0.5")
      .style("fill", "#F5F5F5")
      .attr("class", function(d,index) { return index%2==0 ? "even" : "uneven"; });

  svg.append("g")
      .attr("class", "y axis")
  .append("line")
      .attr("x1", x(0))
      .attr("x2", x(0))
      .attr("y2", height);

  var startp = svg.append("g").attr("class", "legendbox").attr("id", "mylegendbox");
  // this is not nice, we should calculate the bounding box and use that
  var legend_tabs = [0, 150, 300];
  var legend = startp.selectAll(".legend")
      .data(color.domain().slice())
    .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(" + legend_tabs[i] + ",-45)"; });

  legend.append("rect")
      .attr("x", 0)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

  legend.append("text")
      .attr("x", 22)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "begin")
      .style("font" ,"10px sans-serif")
      .text(function(d) { return d; });

  d3.selectAll(".axis path")
      .style("fill", "none")
      .style("stroke", "#000")
      .style("shape-rendering", "crispEdges")

  d3.selectAll(".axis line")
      .style("fill", "none")
      .style("stroke", "#000")
      .style("shape-rendering", "crispEdges")

  var movesize = width/2 - startp.node().getBBox().width/2;
  d3.selectAll(".legendbox").attr("transform", "translate(" + movesize  + ",0)");

// });



}

可以看出,刻度文本的当前位置是右边的。 我尝试了以下想法:

 svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
  .selectAll("text")
    .style("text-anchor", "start");

但它没有将刻度线定位在所需的对齐位置。 任何想法?

2 个答案:

答案 0 :(得分:3)

您可以使Y轴朝向右侧,这样可以将所有标签定位在轴的右侧,左对齐它们:

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("right")// <- 1st step

此时标签会消失,因为它们会被图表的条形遮盖。

但是然后你可以将所有那些左对齐的标签在负X方向上移动一些恒定距离,这样它们就会回到Y轴的左侧,但仍然按照你想要的方式左对齐。 tickPadding()是改变它们的一种方式:

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("right")
  .tickPadding(-180)

以下是您的示例,经过上述修改:http://jsfiddle.net/2khbceut/3/

也许硬编码-180对你来说没问题。如果您需要这个数量是动态的,您可以在轴的每个getBBox()元素上使用text计算它,并将最大宽度作为负偏移量。

答案 1 :(得分:0)

您可以将文本锚设置为&#34; start&#34;并使用translate调整x位置,我在图表模型中添加了以下代码&#34; boxPlotChart.js&#34;

 g.select('.nv-y.nv-axis').selectAll('.tick').selectAll('text')
                .style('text-anchor','start')
                .attr('transform', function(d,i,j) { return 'translate(-14,0)' });

 g.select('.nv-y.nv-axis').selectAll('.nv-axisMaxMin').selectAll('text')
                .style('text-anchor','start')
                .attr('transform', function(d,i,j) { return 'translate(-16,0)' });