【问题标题】:3 dimension (X, Y and Z) graph using D3.js [closed]使用 D3.js 的 3 维(X、Y 和 Z)图 [关闭]
【发布时间】:2014-01-29 08:43:54
【问题描述】:

我正在搜索具有 3 维(x、y 和 z) 并使用 D3.js 的图表。请让我知道是否有任何数据可视化网站可以找到这样的图表,或者d3js.org 上是否有我以某种方式错过的图表。

【问题讨论】:

  • 你需要什么样的3D情节?散射,表面?
  • 3D散点图
  • 你能发布一个你想要实现的例子吗?可以在 D3 中制作 3D 散点图,但表面图可能会更复杂。
  • 图形应该在 3 轴 (xyz) CustomerProductcontent。在客户下,我有 3 个类别(金、银和青铜)。我想根据内容和产品的客户类别绘制图表。
  • This 是我在谷歌上搜索“D3 3D 散点图”时的第一个结果。

标签: javascript d3.js svg graph 3d


【解决方案1】:

由 VividD 和 Lars Kotthoff 链接到的 3D 散点图可能是您所要求的最佳示例,但我会反驳并建议您可能问错了问题。

试图在平面屏幕上模拟三个空间维度总是不完美的,并且难以读取数据。但是,在 D3 中绘制三个不同的 data 维度非常容易。您对两个数据变量使用水平和垂直布局,然后对第三个变量使用大小、形状、颜色或阴影。

如果所有三个数据变量都最好用连续数字表示,那么最好的方法是使用气泡散点图,其中三个显示维度是水平位置、垂直位置和气泡大小。

这是一个示例,它还使用在线交互组件添加通过运动显示的第四个维度:
Bubble Scatterplot -- click for original

您说您的三个维度是客户产品内容。我不知道“内容”是什么类型的值(数字或类别),但我很确定“客户”和“产品”是类别。

这是一个示例,其中使用两个分类维度来布置表格,然后表格的每个单元格都包含一个由第三个数字维度调整大小的圆圈。如果您的第三个变量是一个类别,您可以使用一个形状来指示每对“客户”和“产品”对应的“内容”类型(如果有的话):

(来源:fastly.net)

气泡矩阵 -- 点击查看原文](http://neuralengr.com/asifr/journals/)

这是另一个,其中第三维以颜色而不是大小显示。颜色表示一个连续变量,但您可以轻松选择一组高对比度的颜色来表示类别:
Colour Matrix -- click for original

当然,一个普通的堆叠条形图是另一种显示两个类别和一个数字数量的方式:
Stacked Bar Graphs -- click for original

而且您不必停留在三个数据变量上。如果其中两个数据变量是您不介意分组的类别或数字,则可以使用“小倍数”方法绘制四个变量,在该方法中创建一个表示类别变量的表,然后重复每个表格单元格内的其他两个变量。

像这样:
Scatterplot Matrix -- click for original

或者这个(星期和星期几是数据的两个维度,类别/数量是另外两个):

Pie Chart Small Multiples -- click for original

我希望这给了你很多想法......

【讨论】:

  • 这是对一个没有被问到的问题的非常详细的答案,但它是一个非常好的答案:-) 同样,收藏!
  • 我希望我能给这个答案投票 50 次。
  • 有趣的答案。实际上,我认为如果您拥有真实的空间数据,则应该以 3D 形式将其可视化。 Colin Ware 在他的著作Information Visualization - Perception for Design 中引用了一句话:“对于 3D 可视化系统和一般 3D 用户界面的最终优势,最有力的论据必须是我们生活在 3D世界和我们的大脑已经进化到能够识别 3D 并与之互动”。
  • 这不是一个好的答案。在数据存在于 3d 空间中的情况下,将第三维移动到另一个视觉特征可能会扭曲数据的感知方式。想象一下 3d 词嵌入,其中两个词非常不同,但仅在三维上。它们最终直接重叠在一起,任意突出了它们在 2 维上的相似性,而在不同的投影中,它们相距很远,只有当观众能够仔细评估圆的大小时,它们在 2 维上的相似性才明显。
【解决方案2】:

一种类似于你所寻求的例子是:

3D scatter plot

请注意,此示例使用了X3DOM,这是一种在 HTML 中标准化 3D 呈现的相当新的尝试,并非所有浏览器都支持。


在 X3DOM 中使用 D3.js 的一些额外测试示例:

X3DOM in callback test

D3 X3DOM event test

在 D3 Google 组中搜索 X3DOM。


另一种可能有趣的方法是使用 D3.js 和 Three.js,如下所示:

Showing GPS tracks in 3D with three.js and d3.js


一般来说,D3.js 更倾向于数据可视化而不是科学可视化,这意味着它没有广泛支持显示 3D 空间(显示地理 3D 数据除外,D3.js 非常支持方式,但这不是需要的)。

例如(此示例与您的示例没有直接关系,仅用于说明):D3 提供了用于 2D 绘制树木的算法,但不提供任何用于 3D 放置树木以及随后在2D 屏幕。


如果您不限于 D3.js,也许您可​​以使用其他库更轻松、更快地实现相同的目标,这些库专门为类似于您的目的而编写。例如,您可以使用Pre3D。看看这个example。 Pre3D 不使用 X3DOM,只是在 2D 画布上呈现纯 HTML。我认为它的 3D 图形的动画(旋转)比第一个 D3/X3DOM 示例中的更平滑。

【讨论】:

  • 非常感谢 VividD..它不支持 Firefox!我浏览了示例图,但找不到该图的输入文件。请让我知道数据输入格式。
  • 你能看看这个关于d3的问题stackoverflow.com/questions/67312494/…
【解决方案3】:

我创建了d3-3d,这是一个 d3 插件,可帮助您可视化您的 3d 数据。希望这有助于您实现目标。

【讨论】:

【解决方案4】:

我能找到的最好的例子(都非常简单)是:

Highcharts(3d 散点图)

http://www.highcharts.com/demo/3d-scatter-draggable

Vis.js(各种 3d 选项,例如条形和点)

示例 https://ww3.arb.ca.gov/ei/tools/lib/vis/examples/graph3d/playground/

文档 https://ww3.arb.ca.gov/ei/tools/lib/vis/docs/graph3d.html

只需提供 x、y 和 z 坐标,设置你喜欢的配置,然后你就笑了。

【讨论】:

  • 对于 Vis.js,有没有办法在 3d 图形的“墙壁”上放置网格线或背景颜色?此外,有没有办法添加悬停来显示你已经结束的点?我一直在努力寻找这些选项,但它们却无处可寻。此外,我似乎也找不到其他软件包来做这件事。
  • 抱歉,我不是这些库的超级用户!我用了一点,但不做自己的研究就知道了。
  • 没关系。我一直在寻找一段时间,并没有找到一个好的解决方案。我也不是超级用户。我在这里发了一个帖子:stackoverflow.com/questions/43239072/…希望有人能帮忙!
【解决方案5】:

这里是纯javascript+svg解决方案

let f = (x, z) => Math.cos(z/20)*20 + Math.sin(x/10)*10 + x/3*Math.atan2(z,x);

let cos = Math.cos, sin = Math.sin, xyz = 'xyz'.split(''),
    k = 500, a1 = 0, a2 = 0, far = 300, p, w, h, a,
    points = [], lines = [], s = 100;
    
for (var x = -s; x < s; x += 5) 
for (var z = -s; z < s; z += 5) 
  points.push({x, z, r:2});

for (var i = 0; i < 6; i++) lines.push([
  {x:-s, y:-s, z:-s, color:`hsl(${i*120},55%,55%)`, state:{}},
  {x:i%3==0?s:-s, y:i%3==1?s:-s, z:i%3==2?s:-s, state:{}}
]);

points.forEach(d=>d.state={fill:`rgb(${d.x+s},${(d.y=f(d.x,d.z))+s},${d.z+s})`});
pointsGroup.innerHTML=points.map((d,i)=>`<circle ind="${i}"></circle>`).join('');
linesGroup.innerHTML=lines.map(d=>`<path stroke="${d[0].color}"></path>`).join('');
let circles = pointsGroup.querySelectorAll('circle');
let paths = linesGroup.querySelectorAll('path');

function project(p) {
  let x = p.x*cos(a1) + p.z*sin(a1);
  let z = p.z*cos(a1) - p.x*sin(a1);
  let y = p.y*cos(a2) +   z*sin(a2);
  let d =   z*cos(a2) - p.y*sin(a2) + far;
  p.state.cx = (k/d)*x + w/2;
  p.state.cy = (k/d)*y + h/2;
  p.state.r = far/d*p.r;
}

function render() {
  if (a) for (var i=0; i<3; i++) 
    xyz.forEach((c, j) => lines[i][0][c] = i==j ? -s : (lines[i][1]=a)[c]);
  points.forEach(project);	
  points.sort((a, b) => a.state.r - b.state.r);
  lines.forEach(line => line.forEach(project));	
  points.forEach((d, i) => Object.entries(d.state)
      .forEach(e => circles[i].setAttribute(...e)));
  lines.forEach((l, i) => paths[i].setAttribute('d', 
     `M${l[0].state.cx} ${l[0].state.cy} L${l[1].state.cx} ${l[1].state.cy}`));
}

let evt = (t, f) => addEventListener(t, e => render(f(e)));
evt('click', e => a = points[e.target.getAttribute('ind')])
evt('wheel', e => k *= 1 - Math.sign(e.deltaY)*0.1);
evt('mouseup', e => p = null);
evt('mousedown', e => p = {x: e.x, y: e.y, a1, a2});
evt('mousemove', e => p && (a1 = p.a1-(e.x-p.x)/100) + (a2 = p.a2-(e.y-p.y)/100));
evt('resize', e=>svg.setAttribute('viewBox',`0 0 ${w=innerWidth} ${h=innerHeight}`));
dispatchEvent(new Event('resize'));
&lt;svg id="svg" stroke-width="2"&gt;&lt;g id="pointsGroup"&gt;&lt;/g&gt;&lt;g id="linesGroup"&gt;&lt;/g&gt;&lt;/svg&gt;

【讨论】:

    【解决方案6】:

    看起来更恰当地说是“3D”的新示例已经问世。 http://bl.ocks.org/supereggbert/aff58196188816576af0

    这是我做出的改编:

    http://bl.ocks.org/adrianturcato/cf665b7cca9f6057691a

    【讨论】:

      【解决方案7】:

      Stefan Nieke 最近也在用他的 d3-3d 插件做一些很酷的事情:https://bl.ocks.org/Niekes

      【讨论】:

      • 你可以找到repo here
      猜你喜欢
      • 2015-03-16
      • 2013-02-26
      • 1970-01-01
      • 2012-10-03
      • 2020-12-05
      • 2021-06-09
      • 1970-01-01
      • 2019-11-24
      • 1970-01-01
      相关资源
      最近更新 更多