【问题标题】:Assign distinct y coordinate to each categorical value为每个分类值分配不同的 y 坐标
【发布时间】:2021-05-09 11:00:45
【问题描述】:

我有明确要求在 d3 上下文中计算 y 坐标,但我正在努力......

a) 找到 d3(缩放?)组件和使用模式来交付解决方案

b) 识别任何可以帮助我找到的可导航 d3 API 资源a)

我有一个事件列表,这些事件具有开始和结束时间,并且每个事件都与它们按顺序执行的进程相关联。很自然地将其呈现为多轨界面(有点像音频编辑器或甘特图),其中每个进程/轨道都分配有自己的水平泳道,并且事件根据它们的开始和结束水平布置时间。它可能最终看起来有点像view from a research publication

事件数据项具有对其进程 ID 的引用(在显示的图表中,进程 ID 将是 M1、M2,事件将是标有数字的小框)。我知道每个事件的开始和结束时间(确定它们的 x 坐标和宽度),但我需要将操作的矩形放在正确的进程行(y 坐标)中。

事件列表将随着它们的开始和结束而不断更新,并且将来可能由过滤器/画笔调节。

行数随着进程数的变化而变化。出于这个原因,只有在加入事件列表(并遇到它们引用的所有进程 ID)之后,您才能知道需要多少行、行高,以及每个事件的 y 比例位置应该是什么。当新的事件项进入指向新进程 ID 的选择时,秤应重新调整以添加额外的行。当它退出选择时,它可能是该进程行中的最后一个,因此该行应该消失。

是否存在通过事件数据动态列表的(分类)进程 ID 动态分配事件行的 y 坐标的模式?

如何找到此类案例的模式和解决方案?

【问题讨论】:

  • 你能贴一张你想要达到的目标的图片/草图吗?
  • 谢谢,迈克尔。我发布了一张可能有助于澄清的图片。

标签: d3.js row scale categorical-data


【解决方案1】:

这是一个使用以下数据模型的简单 sn-p:

[
  {
    label: string; // Row label
    color: string; // Row color
    items: [ { label: string; start: number; end: number; }, ...];
  },
  ...
]

sn-p 使用d3.scaleLineard3.axisBottom 例程。

注意:我使用 _top 是因为(出于某种神秘原因)top 已被使用...我想这是 D3 V5 中的错误并建议使用 V6

const data = [
  {
    label: 'M1',
    color: 'red',
    items: [
      {label: 'A', start: 10, end: 12},
      {label: 'B', start: 15, end: 20}
    ]
  },
  {
    label: 'M2',
    color: 'orange',
    items: [
      {label: 'C', start: 0, end: 4},
      {label: 'D', start: 4, end: 6},
      {label: 'E', start: 11, end: 17}
    ]
  },
  {
    label: 'M3',
    color: 'yellow',
    items: [
      {label: 'F', start: 0, end: 3},
      {label: 'G', start: 3, end: 9},
      {label: 'H', start: 9, end: 14}
    ]
  }
];


const ticks = 25;
const left = 50;
const _top = 50;
const rowHeight = 20;
const labelWidth = 30;
const bottom = _top + data.length * rowHeight;

const svg = d3.select("svg");

const xScale = d3.scaleLinear()
  .domain([0, ticks])
  .range([0, 300]);
  
const xAxis = d3.axisBottom()
    .scale(xScale);

svg.append("g")
    .attr('transform', `translate(${left}, ${bottom - 1})`)
  .call(xAxis);
      
let i, j;      
for (i = 0; i <= ticks; i++)
    svg.append('line')
    .attr('x1', xScale(i) + left)
    .attr('x2', xScale(i) + left)
    .attr('y1', _top)
    .attr('y2', bottom)
    .style('stroke', 'black');
    
for (i = 0; i < data.length; i++) {
    svg.append('line')
    .attr('x1', left)
    .attr('x2', xScale(ticks) + left)
    .attr('y1', _top + i * rowHeight)
    .attr('y2', _top + i * rowHeight)
    .style('stroke', 'black');
  svg.append('rect')
    .attr('x', left - labelWidth)
    .attr('y', _top + i * rowHeight)
    .attr('width', labelWidth)
    .attr('height', rowHeight)
    .style('fill', data[i].color)
    .style('stroke', 'black')
  svg.append('text')
    .text(data[i].label)
    .attr('x', left - labelWidth / 2)
    .attr('y', _top + (i + 0.5) * rowHeight)
    .attr('text-anchor', 'middle')
    .attr('alignment-baseline', 'middle')
    .style('fill', 'black');
    
  const items = data[i].items;  
  for (j = 0; j < items.length; j++) {
    const x = left + xScale(items[j].start);
    const width = xScale(items[j].end) - xScale(items[j].start);
  svg.append('rect')
    .attr('x', x)
    .attr('y', _top + i * rowHeight)
    .attr('width', width)
    .attr('height', rowHeight)
    .style('fill', data[i].color)
    .style('stroke', 'black')
    
  svg.append('text')
    .text(items[j].label)
    .attr('x', x + width / 2)
    .attr('y', _top + (i + 0.5) * rowHeight)
    .attr('text-anchor', 'middle')
    .attr('alignment-baseline', 'middle')
    .style('fill', 'black');
    
  }  
}    
  
text {
  font-family: 'Ubuntu';
  font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="400" height="200">
</svg>

【讨论】:

  • 哇,工作量太大了,迈克尔!感谢您对我措辞不佳的问题的耐心等待。刚从 D3 开始。还没有建立一个好的心智模型或工具来起草半完整的问题案例。已经可以计算Typescript+React中的所有坐标结构。使用 D3 原语似乎是关于允许数据驱动数字,使用由选择驱动的有用原语。我想知道存在什么 D3 原语来不硬编码行高 - 总图形高度是已知的,但在数据存在之前不知道行数。
  • 一个相关的问题是如何利用 D3 将事件数据动态地投影到足够面向行的形式中,因为它一开始就不是面向行的。更好的提问者会提供示例数据。我将根据您的出色示例回过头来正确地重新塑造问题。您是否建议不要费心学习 D3 而只是使用 Javascript/Typescript 进行计算然后显式绘制 SVG?
  • 我想我会将您的答案标记为对我写得不好的问题的最佳回答,并按照您的示例编写一个具有适当参考 D3 实现的答案。
  • 受您清晰的回答的启发,我尝试构建一个更清晰的参考示例,并将问题集中在我的规模上,这应该由数据连接驱动stackoverflow.com/questions/67463228/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
  • 2021-11-21
  • 1970-01-01
  • 2019-12-13
  • 2020-10-22
  • 2014-03-21
  • 2020-04-05
相关资源
最近更新 更多