我正在学习D3,我的玩具应用程序是使用Symplectic Velocity Verlet Integration进行二维重力模拟的可视化工具。
我使用绑定结构化数据动画和绘制路径已经取得了相当大的成功,但在我看来,D3并不是真正设计用于将数据附加到多个元素。它假定对于任何给定的数据,有一个清晰而简单的SVG元素应该拥有它,这在DOM内的__data__
属性中直接存储数据时很明显。
但是,目前尚不清楚使用多个SVG元素表示数据的正确方法。例如,我真的更喜欢为每个行星绘制一条路径和一个圆,路径追踪它的过去位置(并且可以应用一堆聪明的线长和颜色插值),以及圆圈绘制了当前位置。
我甚至可以想出一些我想要画的元素:速度的矢量箭头......加速度的矢量箭头......
就我而言,我的主数据结构是这样构造的,并在此结构中动态维护:
var data = [];
function makeParticle(x, y, vx, vy) {
// state vector plus goodies
return [
x, y,
vx, vy,
0, 0,
[] // path
];
}
data.push(makeParticle(400, 100, -0.5, 1));
data.push(makeParticle(300, -100, 0.5, 2)); // and so on
数据的每个元素都是一个行星,它包含当前的状态向量(位置,速度和缓存加速度(积分器所需))以及它的路径历史,这是一个位置的数组,它被截断到某些位置相当长的长度。
目前我正在更新路径历史记录:
var paths = d3.select('svg').selectAll("path").data(data);
paths.enter().append('path'); // put cool transitions here
paths.exit().remove();
paths.attr("stroke", "red")
.attr("d", function(d){
return lineDrawer(d[6]);
})
这很好用,每条路径都跟踪它自己行星路径的副本。
我不能立即明白如何优雅地扩展它以将我的圆圈包含在每条路径的头部。我当然不想将整个数据复制到圆圈的DOM元素中(因为路径数据根本不是必需的)。
根据我的自我回答编辑:
我希望有人可以帮助阐明一种使用“组”的方法,使数据驱动为每个数据绘制的事物集合。例如[position, velocity, force, path]
作为数据,它们分别使用圆圈,箭头闭合路径,箭头闭合路径和开放路径可视化。它也可能完全过度思考它,因为这些属性是固定的。
答案 0 :(得分:0)
我想在通过思考问题的过程中,我清楚地知道我所要做的就是过滤掉数据,这样我才能将位置状态数据附加到selectAll('circle.planet')
而不是全部基准值,包括大规模路径历史数组。这样它就可以获得它负责显示的数据。
似乎我必须更多地阅读有关子选择的内容(我大部分都是为什么(或如果)将子选择限于层次结构的两个维度而感到疑惑),但这似乎是完全合理的。这似乎是合乎逻辑的,如果我想为每个数据绘制4个项目,我只需要以某种方式将我的基准结构的正确子集“分配”给每个SVG可视化元素。