首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >D3支持组合(自下而上)方法吗?

D3支持组合(自下而上)方法吗?
EN

Stack Overflow用户
提问于 2016-06-17 00:14:59
回答 2查看 71关注 0票数 0

通常,当我在三维场景图中对事物建模时,我首先描述低层次的组件,然后将它们组合成越来越复杂的工件。例如,创建一个轮胎,然后创建一个轮毂,然后将它们组合在一起来定义一个车轮。然后拿起车轮,车身和引擎,制造出一辆汽车。最后,把车放在世界上。

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

这两种方法各有优缺点,不过在3D建模方面,我已经看到很多新手纠缠不清,试图用自上而下的方法来描述一个复杂的场景。在自己的空间中考虑低级组件要容易得多,然后如何将它们放置并添加到父结构中。

D3对此有很大的偏见,但我还是决定尝试一种组合建模方法。

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

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

我把它分解成一个非常简单的例子,它仍然会崩溃。

代码语言:javascript
复制
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");
代码语言:javascript
复制
<!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真的不支持这种方法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-17 00:46:02

在考虑了这个问题之后,我对我最初的答案感到不满意,我将在这篇文章的末尾保留这个问题,因为它是正确的,但它不知怎么地回避了“D3支持一种组合(自下而上)的方法吗?”答案应该是肯定的,但不是真的。

  • 是的,因为D3允许模仿自下而上的方法,就像你尝试的那样。这在技术缺陷方面失败了,正如我在下面最初的回答中所解释的那样,这些缺点可以被治愈,但这感觉有些尴尬和凌虐。主要原因是,D3没有提供显式创建元素的方法。在大多数情况下,DOM元素是在执行.append().insert()时隐式创建的。唯一的例外是为这些方法提供一个函数,它返回使用D3以外的方法创建的DOM元素。重要的是要理解,这不是一个缺陷,而是故意的。
  • 不完全是这样,因为D3的核心是将数据绑定到DOM树的层次结构。选材的概念允许保持数据和DOM的相应部分保持同步。这是通过获取选择、将数据绑定到DOM并使用enter、update、exit方案从DOM中添加或删除元素来完成的。此外,当向选择添加元素或在许多情况下执行子选择时,绑定到父元素的数据将由其子元素继承。这需要一种严格的分层自上而下的方法。 无论是否涉及数据,D3的方式都将从选择开始,不管最初是否为空(启动根目录最多的可能是d3.select(document) ),并以自顶向下的方式添加或删除。

长话短说,使用D3来模拟自下而上的方法是可能的,尽管它不是这样设计的。如果您决定尝试一下,请记住,它既不是最优雅的方式,也不是最直观的方法,而且可能会引入一些开销。要以自下而上的方式组合布局,可能值得评估其他更适合这种情况的库。

原始答案

不能使用.append()将D3的选择之一添加到DOM中。但是,您可以向.append()提供一个要追加的返回DOM元素函数。这可以通过将错误行替换为

代码语言:javascript
复制
root.append(function() { return component; });

或者,如果您没有对元素的直接引用,则可以从所选内容中检索它。

代码语言:javascript
复制
root.append(function() { return d3component.node(); });

然后,您的示例可能会如下所示

代码语言:javascript
复制
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(); });
代码语言:javascript
复制
<!DOCTYPE html> <html lang="en">
  <head>
    <script src="http://d3js.org/d3.v3.min.js"></script>
  </head>
  <body>
    <div id="target"></div>
  </body>
</html>

票数 1
EN

Stack Overflow用户

发布于 2016-06-17 00:42:34

使用正常的DOM选择可能会更好,但是使用d3是可能的:

代码语言:javascript
复制
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");
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="target"></div>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37871270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档