条形图条形之间的 d3js 网格线

d3js gridlines between bars for bar charts

我创建了一个简单的 d3js 垂直条形图。我知道通常情况下,要创建网格线,我会使用“tickSize”调用,并给它们一个类似于轴的高度或宽度。

var yGridLine = d3.svg.axis()
  .scale(yScale)
  .tickSize(-width, 0 ,0)
  .tickFormat("")
  .orient("left");

以上代码将创建水平网格线。所以如果我想创建垂直网格线,那么我会修改方向和参考轴(类似于以下未经测试但假设正确的代码)

var xGridLine = d3.svg.axis()
  .scale(xScale)
  .tickSize(-height, 0 ,0)
  .tickFormat("");

现在,问题是,当使用这种方法时,垂直网格线是在垂直条的中间创建的(或者在水平条形图的情况下,水平网格线是在水平条的中间创建的)酒吧),这在视觉上并不令人愉快并且不符合要求。我想要的是让垂直网格线出现在 之间 垂直条(即,在刻度线之间的中心点)。我该怎么做?

例子

In this link,您会发现许多图表,其中垂直网格线位于刻度之间,而不是中心。这就是我想要实现的目标,我的问题是如何实现它?

谢谢。

全部代码:

var data = [{
    name: "Hemant",
    age: 20
  }, {
    name: "Vinay",
    age: 55
  }, {
    name: "Vikas",
    age: 56
  }, {
    name: "Arun",
    age: 88
  }, {
    name: "Varun",
    age: 34
  }, {
    name: "Ajay",
    age: 77
  }],
  w = 600,
  h = 300,
  margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  width = w - margin.left - margin.right,
  height = h - margin.top - margin.bottom;

var mySvg = d3.select("body").append("svg").attr({
    width: w,
    height: h
  }).append("g")
  .attr("transform", 'translate(' + margin.left + ',' + margin.top + ')');

var xScale = d3.scale.ordinal()
  .domain(data.map(function(d) {
    return d.name;
  }))
  .rangeBands([0, width]);

var yScale = d3.scale.linear()
  .domain([0, d3.max(data, function(d) {
    return d.age;
  })])
  .range([height, 0]);

var linearColorScale = d3.scale.linear()
  .domain([0, data.length])
  .range(["#e74c3c", "#8e44ad"]);

var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient("bottom");

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

var yGridLine = d3.svg.axis()
  .scale(yScale)
  .tickSize(-width, 0, 0)
  .tickFormat("")
  .orient("left");

var ordinalColorScale = d3.scale.category20();

mySvg.append("g")
  .classed("gridLine", true)
  .attr("transform", "translate(0,0)")
  .call(yGridLine);

mySvg.selectAll("rect").data(data).enter()
  .append("rect")
  .attr("x", function(d) {
    return xScale(d.name);
  })
  .attr("y", function(d, i) {
    return yScale(d.age);
  })
  .attr("width", function(d) {
    return xScale.rangeBand();
  })
  .attr("height", function(d) {
    return height - yScale(d.age)
  })
  .style("fill", function(d, i) {
    return ordinalColorScale(i);
  })

mySvg.selectAll("text").data(data)
  .enter()
  .append("text")
  .classed("bar", true)
  .attr("x", function(d) {
    return xScale(d.name) + xScale.rangeBand() / 2;
  })
  .attr("dx", 0)
  .attr("y", function(d, i) {
    return yScale(d.age);
  })
  .attr("dy", -6)
  .text(function(d, i) {
    return d.age;
  });

mySvg.append("g")
  .classed("axis", true)
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);


mySvg.append("g")
  .classed("axis", true)
  .attr("transform", "translate(0,0)")
  .call(yAxis);
svg {
  border: 1px solid #ccc;
}

svg rect {
  shape-rendering: crispedges;
}

.bar {
  fill: #000;
  text-anchor: middle;
  font-size: 20px;
}

.axis path,
.axis line {
  fill: none;
  shape-rendering: crispedges;
  stroke: #666;
}

.gridLine path,
.gridLine line {
  fill: none;
  shape-rendering: crispedges;
  stroke: #e4e4e4;
}
<script src="http://d3js.org/d3.v3.min.js"></script>

您可以通过简单地将 .gridLines 翻译成 xScale.rangeBand() / 2 来实现此目的 - 即,一个条形宽度的一半。

var data = [{
    name: "Hemant",
    age: 20
  }, {
    name: "Vinay",
    age: 55
  }, {
    name: "Vikas",
    age: 56
  }, {
    name: "Arun",
    age: 88
  }, {
    name: "Varun",
    age: 34
  }, {
    name: "Ajay",
    age: 77
  }],
  w = 600,
  h = 300,
  margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  width = w - margin.left - margin.right,
  height = h - margin.top - margin.bottom;

var mySvg = d3.select("body").append("svg").attr({
    width: w,
    height: h
  }).append("g")
  .attr("transform", 'translate(' + margin.left + ',' + margin.top + ')');

var xScale = d3.scale.ordinal()
  .domain(data.map(function(d) {
    return d.name;
  }))
  .rangeBands([0, width]);

var yScale = d3.scale.linear()
  .domain([0, d3.max(data, function(d) {
    return d.age;
  })])
  .range([height, 0]);

var linearColorScale = d3.scale.linear()
  .domain([0, data.length])
  .range(["#e74c3c", "#8e44ad"]);

var xAxis = d3.svg.axis()
  .scale(xScale)
  .orient("bottom");

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

var yGridLine = d3.svg.axis()
  .scale(xScale)
  .tickSize(-height, 0, 0)
  .tickFormat("");

var ordinalColorScale = d3.scale.category20();

mySvg.append("g")
  .classed("gridLine", true)
  .attr("transform", "translate(" + [xScale.rangeBand() / 2, height] + ")")
  .call(yGridLine);

mySvg.selectAll("rect").data(data).enter()
  .append("rect")
  .attr("x", function(d) {
    return xScale(d.name);
  })
  .attr("y", function(d, i) {
    return yScale(d.age);
  })
  .attr("width", function(d) {
    return xScale.rangeBand();
  })
  .attr("height", function(d) {
    return height - yScale(d.age)
  })
  .style("fill", function(d, i) {
    return ordinalColorScale(i);
  })

mySvg.selectAll("text").data(data)
  .enter()
  .append("text")
  .classed("bar", true)
  .attr("x", function(d) {
    return xScale(d.name) + xScale.rangeBand() / 2;
  })
  .attr("dx", 0)
  .attr("y", function(d, i) {
    return yScale(d.age);
  })
  .attr("dy", -6)
  .text(function(d, i) {
    return d.age;
  });

mySvg.append("g")
  .classed("axis", true)
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis);


mySvg.append("g")
  .classed("axis", true)
  .attr("transform", "translate(0,0)")
  .call(yAxis);
svg {
  border: 1px solid #ccc;
}

svg rect {
  shape-rendering: crispedges;
}

.bar {
  fill: #000;
  text-anchor: middle;
  font-size: 20px;
}

.axis path,
.axis line {
  fill: none;
  shape-rendering: crispedges;
  stroke: #666;
}

.gridLine path,
.gridLine line {
  fill: none;
  shape-rendering: crispedges;
  stroke: #e4e4e4;
}
<script src="http://d3js.org/d3.v3.min.js"></script>