【问题标题】:d3js gridlines between bars for bar charts条形图的条形之间的d3js网格线
【发布时间】:2020-11-16 04:59:41
【问题描述】:

我创建了一个简单的 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>

【问题讨论】:

    标签: d3.js charts bar-chart gridlines


    【解决方案1】:

    您可以通过简单地将.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>

    【讨论】:

    • 谢谢你,我爱你兄弟般的爱。