d3.js D3(v3.4)边束图和用于加载新数据集的更新按钮

y4ekin9u  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(136)

我有D3(v3.4)边绑定图表,并且我希望通过单击“更新”按钮使用新数据集更新图表。我希望看到图表更新,显示data2.json中的数据(而不是data1.json)。我目前有一个更新按钮和一个updateData的开始()函数,该函数只读取新数据集,虽然我不确定我的代码的哪些部分需要包含在这个函数中以通过转换更新。我知道图表的某些部分需要重新渲染,这不是一个简单地加载到一个新的数据集的情况。我使用这个Update d3.js data with button press的例子作为基础,虽然因为它是一个折线图,转换更新简单得多,所以对我的边束图帮助不大。我下面的代码代表了一个最小的可重现的例子。

HTML/JS格式

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  5. <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'></script>
  6. <script src="https://d3js.org/d3.v4.js"></script>
  7. <style>
  8. .node {
  9. font: 300 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
  10. fill: rgb(0, 0, 0, .6);
  11. }
  12. .link {
  13. stroke: steelblue;
  14. fill: none;
  15. pointer-events: none;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <div class="grid-container"></div>
  21. <div class="grid-item" id="chart">
  22. <div id="my_dataviz"></div>
  23. <script>
  24. var diameter = 760,
  25. radius = diameter / 2;
  26. innerRadius = radius - 160;
  27. var cluster = d3.cluster()
  28. .size([360, innerRadius]);
  29. var line = d3.radialLine()
  30. .curve(d3.curveBundle.beta(0.85))
  31. .radius(function(d) { return d.y; })
  32. .angle(function(d) { return d.x / 180 * Math.PI; });
  33. var svg = d3.select("body").append("svg")
  34. .attr("width", diameter)
  35. .attr("height", diameter)
  36. .append("g")
  37. .attr("transform", "translate(" + radius + "," + radius + ")");
  38. var link = svg.append("g").selectAll(".link"),
  39. node = svg.append("g").selectAll(".node");
  40. d3.json("data1.json", function(error, classes) {
  41. if (error) throw error;
  42. var root = packageHierarchy(classes)
  43. .sum(function(d) { return d.size; });
  44. cluster(root);
  45. link = link
  46. .data(packageImports(root.leaves()))
  47. .enter().append("path")
  48. .each(function(d) { d.source = d[0], d.target = d[d.length - 1]; })
  49. .attr("class", "link")
  50. .attr("d", line);
  51. node = node
  52. .data(root.leaves())
  53. .enter().append("text")
  54. .attr("class", "node")
  55. .attr("dy", "0.31em")
  56. .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); })
  57. .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
  58. .text(function(d) { return d.data.key; })
  59. .on("mouseover", mouseovered)
  60. .on("mouseout", mouseouted);
  61. });
  62. function mouseovered(d) {
  63. node
  64. .each(function(n) { n.target = n.source = false; });
  65. link
  66. .classed("link--target", function(l) { if (l.target === d) return l.source.source = true; })
  67. .classed("link--source", function(l) { if (l.source === d) return l.target.target = true; })
  68. .filter(function(l) { return l.target === d || l.source === d; })
  69. .raise();
  70. node
  71. .classed("node--target", function(n) { return n.target; })
  72. .classed("node--source", function(n) { return n.source; });
  73. }
  74. function mouseouted(d) {
  75. link
  76. .classed("link--target", false)
  77. .classed("link--source", false);
  78. node
  79. .classed("node--target", false)
  80. .classed("node--source", false);
  81. }
  82. // Lazily construct the package hierarchy from class names.
  83. function packageHierarchy(classes) {
  84. var map = {};
  85. function find(name, data) {
  86. var node = map[name], i;
  87. if (!node) {
  88. node = map[name] = data || {name: name, children: []};
  89. if (name.length) {
  90. node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
  91. node.parent.children.push(node);
  92. node.key = name.substring(i + 1);
  93. }
  94. }
  95. return node;
  96. }
  97. classes.forEach(function(d) {
  98. find(d.name, d);
  99. });
  100. return d3.hierarchy(map[""]);
  101. }
  102. // Return a list of imports for the given array of nodes.
  103. function packageImports(nodes) {
  104. var map = {},
  105. imports = [];
  106. // Compute a map from name to node.
  107. nodes.forEach(function(d) {
  108. map[d.data.name] = d;
  109. });
  110. // For each import, construct a link from the source to target node.
  111. nodes.forEach(function(d) {
  112. if (d.data.imports) d.data.imports.forEach(function(i) {
  113. imports.push(map[d.data.name].path(map[i]));
  114. });
  115. });
  116. return imports;
  117. }
  118. // update data function
  119. function updateData() {
  120. d3.json("data1.json", function(error, classes) {
  121. if (error) throw error;
  122. var root = packageHierarchy(classes)
  123. .sum(function(d) { return d.size; });
  124. var svg = d3.select("body").transition();
  125. });
  126. }
  127. </script>
  128. </div>
  129. </div>
  130. </body>
  131. <div id="option">
  132. <input name="updateButton"
  133. type="button"
  134. value="Update"
  135. onclick="updateData()"
  136. />
  137. </div>
  138. </html>

数据1.json

  1. [
  2. {
  3. "name": "flare.A.dataA",
  4. "imports": [
  5. "flare.B.dataB"
  6. ]
  7. },
  8. {
  9. "name": "flare.B.dataB",
  10. "imports": [
  11. "flare.A.dataA"
  12. ]
  13. }
  14. ]

数据2.json

  1. [
  2. {
  3. "name": "flare.A.newdataA",
  4. "imports": [
  5. "flare.B.newdataB"
  6. ]
  7. },
  8. {
  9. "name": "flare.B.newdataB",
  10. "imports": [
  11. "flare.A.newdataA"
  12. ]
  13. }
  14. ]

我找不到任何带有更新按钮的边束图的例子。任何帮助都是感激不尽的!

up9lanfz

up9lanfz1#

我试着编辑你的代码,并能够做到这一点。要更新数据,我们需要使用enter,update和exit方法。在v3中,我记得,当我们输入新的数据,这将创建任何丢失的链接或节点,并使用exit()中,我们可以删除不存在的节点和链接。回车后,我们添加新节点,链接,然后更新它的属性。实际上我们可以使用相同的函数来创建和更新,你可以尝试一下。我不知道为什么newDataB没有作为节点出现在下面的函数中。我的示例数据似乎有问题。你的新示例数据与下面的代码一起工作得很好。
第一个

jhkqcmku

jhkqcmku2#

请尝试以下操作:

  1. transition().duration(1000)
  2. .ease("elastic")
  3. .call(draw);

D3 transitions on enter/update/remove开始
也可以
D3.js update with transition

相关问题