gpt4 book ai didi

javascript - d3 中的并排路径

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:14:42 27 4
gpt4 key购买 nike

我正在尝试一种让路径彼此相邻显示的方法,以便它们相互插入(考虑宽度和相邻点)而不重叠。

这是我的 fiddle ,主要是根据示例拼凑而成 https://jsfiddle.net/crimsonbinome22/k2xqn24x/

var LineGroup = svg.append("g")
.attr("class","line");

var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return (d.x); })
.y(function(d) { return (d.y); })
;

LineGroup.selectAll(".line")
.data(series)
.enter().append("path")
.attr("class", "line")
.attr("d", function(d){ return line(d.p); })
.attr("stroke", function(d){ return d.c; })
.attr("stroke-width", function(d){ return d.w; })
.attr("fill", "none");

这就是我希望在 this image here 中实现的目标,基本上:

  • 对于所有落在同一点上的线,将它们推向该点的左侧或右侧,使它们一起以该点为中心。
  • 将线宽考虑在内,这样它们就不会重叠,也不会在它们之间留下空白。
  • 能够处理具有不同点数的路径(示例中的最大值为 3,但我想处理最多 10 个)
    • 请注意,尽管重叠的点始终具有相同的索引(它们不会循环,而是像树一样向外延伸)
  • 能够处理落在同一点的不同数量的线路。

我遇到的一些问题:

  • 我是 d3 的新手,我发现函数有点令人费解。甚至不确定如何开始应用可以移动线条的逻辑。
  • 我的数据结构中有一些冗余信息,例如 r 代表等级(决定是向左推还是向右推)和 w 代表宽度,这两者对于特定行来说总是相同的。
  • 我有很多数据,因此此处使用的数据结构不适用于我拥有的 csv 数据。也许现在可以跳过这个问题,稍后我会为那个问题提出一个新问题。

我四处搜索,但找不到任何有关如何执行此操作的示例。在某种程度上,它几乎就像一个和弦图,但有点不同,我找不到太多相关的代码来重用。任何关于如何实现这一目标的帮助(无论是使用我已经开始的方法,还是完全不同的方法,如果我错过了它)将不胜感激。

最佳答案

我会按照以下步骤进行:

  • 计算一组节点对象,即一条线访问的每个点对应一个对象
  • 计算此节点上的(即,为每个节点添加指向其父节点和子节点的链接)
  • 确保任何节点的子节点根据它们与该节点形成的 Angular 排序
  • 此时,每一行现在只依赖于它的最终节点
  • 为每个节点计算经过的有序行列表
    • 自下而上访问所有节点(即从叶子开始)
    • “遍历”列表是子列表+在当前节点结束的所有行的串联
  • 对于每个节点,计算一个偏移量数组(通过对连续宽度求和通过的线路)
  • 最后,对于每一行和行中的每个节点,检查偏移数组以了解行必须移动多少

编辑:运行示例 https://jsfiddle.net/toh7d9tq/1/

我在最后两个步骤(计算偏移量)中使用了一种略有不同的方法:我实际上为每个系列创建了一个新的 p 数组,其中包含一对 {node, offset }。这样可以更轻松地访问绘图函数中的所有相关数据。

我需要添加一个人造根以获得漂亮的起始线(并使递归和 Angular 等更容易),如果需要,您可以在绘图阶段跳过它。

  function key(p) {
return p.time+"_"+p.value
}

// a node has fields:
// - time/value (coordinates)
// - series (set of series going through)
// - parent/children (tree structure)
// - direction: angle of the arc coming from the parent

//artificial root
var root={time:200, value:height, series:[], direction:-Math.PI/2};

//set of nodes
var nodes = d3.map([root], key);
//create nodes, link each series to the corresponding leaf
series.forEach(function(s){
s.pWithOffset=[]; //this will be filled later on
var parent=root;
s.p.forEach(function(d) {
var n=nodes.get(key(d));
if (!n) {
//create node at given coordinates if does not exist
n={time:d.time,
value:d.value,
parent:parent,
series:[],
direction:Math.atan2(d.value-parent.value, d.time-parent.time)};
nodes.set(key(n),n);
//add node to the parent's children
if (!parent.children) parent.children=[];
parent.children.push(n);
}
//this node is the parent of the next one
parent=n;
})
//last node is the leaf of this series
s.leafNode=parent;
parent.series.push(s);
})

//sort children by direction
nodes.values().forEach(function(n){
if (n.children)
n.children.sort(function (a,b){
if (a.direction>n.direction)
return a.direction-b.direction;
});
});

//recursively list all series through each node (bottom-up)
function listSeries(n) {
if (!n.children) return;
n.children.forEach(listSeries);
n.series=d3.merge(n.children.map(function(c){return c.series}));
}
listSeries(root);
//compute offsets for each series in each node, and add them as a list to the corresponding series
//in a first time, this is not centered
function listOffsets(n) {
var offset=0;
n.series.forEach(function(s){
s.pWithOffset.push( {node:n, offset:offset+s.w/2})
offset+=s.w;
})
n.totalOffset=offset;
if (n.children)
n.children.forEach(listOffsets);
}
listOffsets(root);

然后在绘图部分:

var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return (d.node.time-Math.sin(d.node.direction)*(d.offset-d.node.totalOffset/2)); })
.y(function(d) { return (d.node.value+Math.cos(d.node.direction)*(d.offset-d.node.totalOffset/2)); })
;

LineGroup.selectAll(".line")
.data(series)
.enter().append("path")
.attr("class", "line")
.attr("d", function(d){ return line(d.pWithOffset); })
.attr("stroke", function(d){ return d.c; })
.attr("stroke-width", function(d){ return d.w; })
.attr("fill", "none");

关于javascript - d3 中的并排路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34832766/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com