DojoD3ForceDirectedGraph.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. define([
  2. "dojo/_base/declare",
  3. "dojo/_base/lang",
  4. "dojo/_base/array",
  5. "./DojoD3",
  6. "./Mapping",
  7. "dojo/text!./templates/DojoD3ForceDirectedGraph.css"
  8. ], function (declare, lang, arrayUtil,
  9. DojoD3, Mapping,
  10. css) {
  11. return declare([Mapping, DojoD3], {
  12. mapping:{
  13. vertices: {
  14. display: "Vertices",
  15. fields: {
  16. id: "ID",
  17. label: "Label",
  18. category: "Category"
  19. }
  20. },
  21. edges: {
  22. display: "Edges",
  23. fields: {
  24. sourceID: "Source ID",
  25. targetID: "Target ID",
  26. weight: "Weight"
  27. }
  28. }
  29. },
  30. constructor: function (mappings, target) {
  31. if (mappings)
  32. this.setFieldMappings(mappings);
  33. if (target)
  34. this.renderTo(target);
  35. },
  36. resize: function (args) {
  37. // No resize needed
  38. },
  39. renderTo: function (_target) {
  40. _target = lang.mixin({
  41. css: css,
  42. innerRadiusPct: 0
  43. }, _target);
  44. this.inherited(arguments);
  45. },
  46. display: function (vertices, edges) {
  47. if (vertices)
  48. this.setData(vertices, "vertices");
  49. if (edges)
  50. this.setData(edges, "edges");
  51. var vertices = this.getMappedData("vertices");
  52. idIndex = {};
  53. arrayUtil.forEach(vertices, function (item, idx) {
  54. idIndex[item.id] = idx;
  55. });
  56. var edges = this.getMappedData("edges");
  57. arrayUtil.forEach(edges, function (item, idx) {
  58. item.source = idIndex[item.sourceID];
  59. item.target = idIndex[item.targetID];
  60. });
  61. var color = d3.scale.category20();
  62. var force = d3.layout.force().charge(-120).linkDistance(30).size([this.target.width, this.target.height]);
  63. force.nodes(vertices).links(edges);
  64. var link = this.SvgG.selectAll(".linkFD").data(edges).enter().append("line")
  65. .style("stroke-width", function (e) { return Math.sqrt(e.weight) })
  66. .style("stroke", "#999")
  67. .style("stroke-opacity", ".6")
  68. ;
  69. var node = this.SvgG.selectAll(".nodeFD").data(vertices).enter().append("circle")
  70. .style("fill", function (e) { return color(e.category) })
  71. .style("stroke", "#fff")
  72. .style("stroke-width", "1.5px")
  73. .attr("r", 5)
  74. .call(force.drag)
  75. ;
  76. node.append("title").text(function (e) { return e.name });
  77. force.on("tick", function () {
  78. link
  79. .attr("x1", function (e) { return e.source.x })
  80. .attr("y1", function (e) { return e.source.y })
  81. .attr("x2", function (e) { return e.target.x })
  82. .attr("y2", function (e) { return e.target.y })
  83. ;
  84. node
  85. .attr("cx", function (e) { return e.x })
  86. .attr("cy", function (e) { return e.y })
  87. ;
  88. });
  89. var n = vertices.length;
  90. var context = this;
  91. arrayUtil.forEach(vertices, function (e, t) {
  92. e.x = e.y = context.target.width / n * t
  93. });
  94. force.start();
  95. for (var i = n; i > 0; --i) {
  96. force.tick()
  97. }
  98. force.stop();
  99. }
  100. });
  101. });