【问题标题】:D3.js: range rather than point time axis labelsD3.js:范围而不是点时间轴标签
【发布时间】:2013-12-11 12:33:22
【问题描述】:

我有一个图表,其中包含每天的数据点,但我对 x 轴的默认设置不满意。

默认的 x 轴选择要标记的点,例如使用xAxis.ticks(d3.time.month); 时,它将用该月的名称标记每个月的第一天:

  |-------|-------|-------|-------|-------|-------|
 nov     dec     jan     feb     mar     apr     may

这适用于条形图,上面的每个月份只有一个条形图,但对于面积图来说会产生误导,例如'dec' 中的 'd' 出现在 11 月 28 日、29 日和 30 日的数据点下方。

我希望它标记月份所涵盖的范围(刻度之间的间隙):

  |-------|-------|-------|-------|-------|-------|
     nov     dec     jan     feb     mar     apr  

有什么简单的方法可以在高层次上指定它吗?

【问题讨论】:

  • 类似this?如果您想进一步移动标签,也可以调整dx
  • @LarsKotthoff 那些出现在它们刻度的右侧,而不是在它们的范围内。
  • 是的,这是您在不修改源代码的情况下唯一可以做到的方法。因此,要使它们出现在范围的中间,您需要向元素添加偏移量 (dx)。将文本锚留在中间并将它们偏移间隔宽度的一半可能会更容易。
  • dx 会根据当月的天数而变化
  • 当然可以,但是您可以动态计算区间的宽度。

标签: d3.js axis-labels


【解决方案1】:

(2019) 使用最新的 d3v5、其他 stackoverflow 响应、1mbostock trick to select and edit the labels text propertyaxis styling

首先给出x_scaleticks 的数量,您可以计算所有刻度的渲染像素距离,包括非线性比例。下面的函数返回一个带有刻度距离/空格的数组。

// ticksDistance is constant for a specific x_scale
// apply scale to ticks and calcule distance
const getTicksDistance = (scale) => {
      const ticks = scale.ticks(); // return array with ticks
      const spaces = []
      for(let i=0; i < ticks.length - 1; i++){
        spaces.push(scale(ticks[i+1]) - scale(ticks[i]))
      }
      return spaces;
};
const ticksSpacingTime = getTicksDistance(x_scale_time);

然后使用该距离将标签从其当前位置移动,索引i 为您提供 d3 在文本标签上迭代的位置。

svg.append("g")
    .attr("class", "x-axis-shifted")
    .attr("transform", "translate(0,100)")
    .call(x_axis)
  .selectAll("text")
    .attr("x", (d,i) => ticksSpacingTime[i]/2)

const x_scale_time = d3.scaleTime()
    .domain([new Date(2017,12,1),new Date()])
    .range([0, 960]);
    
const x_axis_time = d3.axisBottom()
    .scale(x_scale_time)
    .ticks(d3.timeMonth.every(1))
    

const x_scale_pow = d3.scalePow().exponent(2)
    .domain([0,20000])
    .range([0, 960]);
    
const x_axis_pow = d3.axisBottom()
    .scale(x_scale_pow)
    .ticks(10)
    
// ticksDistance is constant for a specific x_scale
const getTicksDistance = (scale) => {
      const ticks = scale.ticks();
      const spaces = []
      for(let i=0; i < ticks.length - 1; i++){
        spaces.push(scale(ticks[i+1]) - scale(ticks[i]))
      }
      return spaces;
};

//you have to recalculate when x_scale or ticks change
const ticksSpacingTime = getTicksDistance(x_scale_time);
const ticksSpacingPow = getTicksDistance(x_scale_pow);

const svg = d3.select("body").append("svg")
    .attr("width", "500px")
    .attr("height","350px")
    .style("width", "100%")
    .style("height", "auto");

// normal 
svg.append("g")
    .attr("class", "x-axis-time")
    .attr("transform", "translate(0,0)")
    .call(x_axis_time)
    
// shift labels to half of the ticks distance
svg.append("g")
    .attr("class", "x-axis-time-shifted")
    .attr("transform", "translate(0,40)")
    .call(x_axis_time)
  .selectAll("text")
    .attr("x", (d,i) => ticksSpacingTime[i]/2)


// normal 
svg.append("g")
    .attr("class", "x-axis")
    .attr("transform", "translate(0,110)")
    .call(x_axis_pow)
    
// shift labels to half of the ticks distance
svg.append("g")
    .attr("class", "x-axis-shifted")
    .attr("transform", "translate(0,150)")
    .call(x_axis_pow)
  .selectAll("text")
    .attr("x", (d,i) => ticksSpacingPow[i]/2)
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"&gt;&lt;/script&gt;

【讨论】:

    【解决方案2】:

    要使它们出现在范围的中间,您需要向 text 元素添加偏移量 (dx)。此偏移量将等于间隔大小的一半,您可以动态计算。

    这是一个example,它做了非常相似的事情。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,并通过使用另一个移动 15 天的 X 轴刻度来解决它。

      // scale is your usual x scale. change dates on the domain by 15 days
      var d0 = scale.domain()[0];
      d0.setDate(d0.getDate() - 15);
      var d1 = scale.domain()[1];
      d1.setDate(d1.getDate() - 15);
      
      // use this new x scale for the axis only
      new_scale = d3.time.scale().domain([d0, d1]).range(scale.range());
      d3.svg.axis().scale(new_scale);
      

      这样您就没有笨拙的文本转换,仍然将所有繁重的工作留给 d3。为了显示刻度,您可以使用具有正常比例的第二个 x 轴。

      【讨论】:

        猜你喜欢
        • 2017-12-24
        • 2012-08-16
        • 2021-10-11
        • 2012-07-30
        • 2022-01-03
        • 1970-01-01
        • 2012-07-24
        • 2014-02-02
        • 2013-08-20
        相关资源
        最近更新 更多