首页 > 解决方案 > 如何在 D3 轴和图表之间应用填充?

问题描述

通常图表数据从 Y 轴底部和 X 轴左侧开始。但是,我尝试在 D3 中创建此条形图,该条形图从 Y 轴底部上方 30px 开始,在 X 轴左侧右侧 30px 处开始(参见下面的模型设计)。30px 的内边距也应保持在顶部和右侧。

我无法理解这应该如何实现,因为轴线仍应一直绘制,但刻度线和条形图数据应一直填充 30px,并且应保持比例。

注意:为了清楚起见,我删除了其余的刻度和刻度值。X 轴刻度应放置在每个条的中间。

在此处输入图像描述

标签: javascriptnode.jsd3.js

解决方案


为了实现你想要的,你必须改变天平的设置。由于您有条形图,我假设您有:

  • x 位置的带刻度;
  • y 位置的线性刻度;

另外,由于您没有共享任何运行代码,因此我将根据 d3noob 的这个基本条形图来回答

第一步是设置填充:

const horPadding = 30;
const vertPadding = 30;

现在让我们改变尺度:

乐队规模

为了在波段比例中设置填充,我们将使用scale.paddingOuter.

因为传递给该方法的值是 的倍数scale.step()(也就是说,如果你传递1它等于传递scale.step()),我们将使用它来计算 30px 的填充。数学很简单:

scale.paddingOuter(horPadding / x.step());

线性刻度

这里的数学有点复杂。基本上,我们将计算我们必须低于零才能获得正好 30px(假设您的下域为零,这是条形图中非常基本的规则!)。

这可以用这个作为域的第一个值来完成,替换0

-(d3.max(data, function(d) {
    return d.sales;
}) * vertPadding / height)

这里,sales是用于条形高度的属性,height显然是用于比例和轴的高度。根据您的需要更改它们。

然后,不要忘记使用scale(0)设置矩形的底边。在我分享的 d3noob 代码中,这将是:

return y(0) - y(d.sales); 

这是结果:

var csv = `salesperson,sales
Bob,33
Robin,12
Anne,41
Mark,16
Joe,59
Eve,38`;

const horPadding = 30;
const vertPadding = 30;

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  width = 600 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

var x = d3.scaleBand()
  .range([0, width])
  .padding(0.1);
var y = d3.scaleLinear()
  .range([height, 0]);

var svg = d3.select("body").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 + ")");

const data = d3.csvParse(csv, d3.autoType);

x.domain(data.map(function(d) {
    return d.salesperson;
  }))
  .paddingOuter(horPadding / x.step());

y.domain([-(d3.max(data, function(d) {
  return d.sales;
}) * vertPadding / height), d3.max(data, function(d) {
  return d.sales;
})])


svg.selectAll(".bar")
  .data(data)
  .enter().append("rect")
  .attr("class", "bar")
  .attr("x", function(d) {
    return x(d.salesperson);
  })
  .attr("width", x.bandwidth())
  .attr("y", function(d) {
    return y(d.sales);
  })
  .attr("height", function(d) {
    return y(0) - y(d.sales);
  });

svg.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x));

svg.append("g")
  .call(d3.axisLeft(y));
.bar {
  fill: steelblue;
}
<script src="//d3js.org/d3.v4.min.js"></script>


推荐阅读