D3是否支持组合(自下而上)方法?

时间:2016-06-17 00:15:00

标签: d3.js

通常,当我对事物进行建模时,例如在3D场景图中,我首先描述低级组件,然后将它们组合成越来越复杂的工件。例如,创建一个轮胎,然后是一些螺母,然后是一个轮毂,并将它们组合在一起以形成一个轮子。然后拿起车轮,车身和发动机并制造一辆汽车。最后,将汽车放在世界各地。

然而,D3通常以分解(自上而下建模)表示。因此,您可能需要创建一个表,然后定义其标题,然后定义其行,然后定义每行中的单元格。

这两种方法都有优点和缺点,但对于3D建模,我看到很多新手都试图用自上而下的方法描述一个复杂的场景。更容易思考自己空间中的低级组件,然后如何将它们放置并添加到它们的父结构中。

D3严重偏向于此,但我决定尝试使用组合建模方法。

简而言之,它似乎不受支持。为了具体说明我的意思,我首先尝试创建一个表头组件(),然后将表头附加到表元素。我收到此错误消息:

Uncaught InvalidCharacterError: Failed to execute 'createElement' on 'Document': The tag name provided ('[object HTMLDivElement]') is not a valid name.

我将其分解为一个非常简单的例子,它仍然会破坏。

var component = document.createElement("div");
var d3component = d3.select(component).text("XYZZY");
var root = d3.select('#target');
// root.append(d3component);        // FAILURE
root.append('div').text("FROTZ");
<!DOCTYPE html> <html lang="en">
  <head>
    <script src="http://d3js.org/d3.v3.min.js"></script>
  </head>
  <body>
    <div id="target"></div>
  </body>
</html>

如果您将root.append(d3component)行注释掉,则会成功运行。但是,如果取消注释,D3将失败并显示上述错误消息。

我在这里遗漏了什么,或者这种方法真的不受D3的支持吗?

2 个答案:

答案 0 :(得分:1)

考虑到这个问题的第二个想法,我对我的原始答案不满意,我将在本文末尾保留,因为它是正确的,但它以某种方式引起了&#的问题34; D3是否支持组合(自下而上)方法?&#34; 。答案应该是非常,但不是真的

  • ,因为D3允许以您尝试的方式模仿自下而上的方法。由于我在下面的原始答案中解释过,这可以解决技术上的缺陷,但这感觉有点尴尬和辱骂。主要原因是,D3没有提供明确创建元素的方法。在大多数情况下,在执行.append().insert()时会隐式创建DOM元素。唯一的例外是为这些方法提供一个函数,该函数返回使用D3之外的方法创建的DOM元素。重要的是要理解,这不是一种缺陷,而是设计上的。

  • 不是,因为它的核心D3是将数据绑定到DOM树的层次结构。 selections的概念允许保持您的数据和DOM的相应部分同步。这是通过获取选择,将数据绑定到它并使用输入,更新,退出方案来添加或删除DOM中的元素来完成的。此外,在向选择中添加元素或在进行子选择时,在许多情况下,绑定到父元素的数据将由其子元素继承。这要求采用严格的分层自上而下的方法。

    是否有数据涉及,以D3方式执行将从选择开始,因为它最初为空(或者最好是d3.select(document)从最开始)并添加或删除以自上而下的方式来自它。

简而言之,可以使用D3来模拟自下而上的方法,尽管它没有被设计成以这种方式使用。如果您决定尝试一下,请记住,它既不是最优雅也不是最直观的方式,并且可能会引入一些开销。要以自下而上的方式构建您的布局,可能值得评估可能更适合此类的其他库。

原始答案

您无法使用.append()向DOM中添加D3的一个选项。但是,您可以向.append()提供要追加returns a DOM element的函数。这可以通过用

替换错误的行来完成
root.append(function() { return component; });

或者,如果您没有直接引用该元素,您可以从选择中检索它

root.append(function() { return d3component.node(); });

您的示例可能看起来像这样

&#13;
&#13;
var component = document.createElement("div");
var d3component = d3.select(component).text("XYZZY");
var root = d3.select('#target');
root.append(function() { return component; });
// ...or...
//root.append(function() { return d3component.node(); });
&#13;
<!DOCTYPE html> <html lang="en">
  <head>
    <script src="http://d3js.org/d3.v3.min.js"></script>
  </head>
  <body>
    <div id="target"></div>
  </body>
</html>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

对于正常的DOM选择,你可能会更好,但是d3:

是可能的

&#13;
&#13;
var component = document.createElementNS("http://www.w3.org/1999/xhtml","div"); // note use of createElementNS
d3.select(component).text("XYZZY");
var root = d3.select('#target');
root[0][0].appendChild(component);
root.append('div').text("FROTZ");
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="target"></div>
&#13;
&#13;
&#13;