javascript - 在 d3.js 中的每个 X 轴日期标签下方添加自定义文本

标签 javascript d3.js

我在 d3.js 中有一个折线图。

X 轴具有日期,定义如下:

g.append("g")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b/%d/%Y")).ticks(d3.timeYear))
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dy", ".25em")
    .attr("transform", "rotate(-45)");

我想在每个日期旁边显示附加信息。具体来说,是基于该日期行的值的计算。为简单起见,假设我只想显示该点的线值乘以 3。因此,如果在 2020 年 4 月 19 日,线的值为 150,则 X 轴应为:
04/19/2020
450

如果我尝试使用轴变换将文本直接插入轴标签,则会出现错误,大概是因为它不再是有效的日期/时间格式。所以我想我必须将文本作为单独的元素添加,但我不明白如何遍历图形上的每个点并计算要显示的正确文本。对于每种情况,计算正确的 Y 位置应该很容易(y 是图形的整个高度加上一些固定偏移量),因此问题是迭代并为每个点设置正确的 X 和值。

Fiddle

最佳答案

您可以定义创建自定义 tickFormat方法。例如:

function customFormat(e) {
    // do whatever calculation you like with e here
    return d3.timeFormat("%b/%d/%Y")(e) + "-" + e.getDay();
}

然后你可以把它传递给tickFormat像这样:
d3.axisBottom(x).tickFormat(customFormat).ticks(d3.timeYear)

这是它的样子:

Screenshot of x-axis with extra data

如果自定义文本需要在现有轴下方,您可以添加另一个 x 轴。您也可以使用自定义 tickFormat并使其线条不可见。例如:
function customFormat(e) {
  return e.getDay();
}

let anotheraxis = g.append("g")
  .attr("transform", "translate(0," + (height + 60) + ")")
  .call(d3.axisBottom(x).tickFormat(customFormat).ticks(d3.timeYear));

// Hide the new axis' lines
anotheraxis
  .selectAll("line")
  .style('opacity', 0);

anotheraxis
  .selectAll("path")
  .style('opacity', 0);

这将如下所示:

Screenshot of an extra x-axis with extra data

您提到了“基于该日期行的值的计算”。当然,如果您的数据是由某种函数生成的,您可以将自定义格式的刻度值传递给该函数。但是,如果您有一组数据点,例如在您的 JSFiddle 示例中,则必须使用插值来计算曲线在该刻度值处的值。 D3 似乎没有提供一种简单的方法来做到这一点,但 these questions可能是你的起点。

也可以使用 tickValues 方法来设置轴应该具有哪些特定刻度。如果将其设置为数据的 x 值,则不需要进行任何插值,因为您已经有了 y 值。

例如,您可以创建一个仅包含数据日期的数组:
let dates = data.map((x) => x.date);

然后构造一个包含日期数据值的对象:
let date_values = data.reduce((o, x) => { o[x.date] = x.value; return o;}, {});

然后您可以创建一个使用 date_values 的自定义格式。对象获取日期的值并将其乘以 3:
function customFormat(e) {
   return d3.timeFormat("%b/%d/%Y")(e) + "-" + (3 * date_values[e]);
}

最后,使用自定义格式和 dates轴数组:
.call(d3.axisBottom(x).tickFormat(customFormat).tickValues(dates))

我创建了一个演示 here .这是它的样子:

Screenshot of axis containing only known data points for ticks

另一种向轴底部添加值的方法是选择所有 .tick元素并添加一个新的 text他们每个人的元素。例如:
let axis_bottom = g.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b/%d/%Y")).ticks(d3.timeYear).ticks(5));

axis_bottom
  .selectAll("text")
  .attr("dy", ".5em");

axis_bottom
  .selectAll('.tick')
  .append('text')
  .attr("dy", "2.5em")
  .attr("fill", "currentColor")
  .text((e) => {
      // Do whatever calculation on e here.
      return 'abcd';
  });

这是它的样子:

Screenshot of extra text elements for every .tick element

关于javascript - 在 d3.js 中的每个 X 轴日期标签下方添加自定义文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61320277/

相关文章:

javascript - 有没有办法在搜索栏中用 php 调用模式?

javascript - D3.js 版本 4 使节点具有粘性

javascript - 使用 D3.csv 在 DC.JS 中加载 CSV 文件

javascript - 如何将 d3.svg.axis 限制为整数标签?

Javascript 名称数组输入选择器 (name[sometext])

javascript - 查找方法(不是 queryBuilder)的嵌套 AND 和 OR 条件

javascript - "Could not find Installable ISAM"从 JavaScript 连接到 Jet.OLEDB 时出错

javascript - Dojo Dgrid 行选择不起作用并检索 dgrid 选择器的值?

javascript - 使用 d3.js 在 Canvas 上进行语义缩放

javascript - 如何在d3js中垂直树