DojoD3CooccurrenceGraph.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. define([
  2. "dojo/_base/declare",
  3. "dojo/_base/lang",
  4. "dojo/_base/array",
  5. "./DojoD3",
  6. "./Mapping",
  7. "dojo/text!./templates/DojoD3CooccurrenceGraph.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. renderTo: function (_target) {
  37. _target = lang.mixin({
  38. css: css,
  39. margin: { top: 80, right: 0, bottom: 20, left: 100 }
  40. }, _target);
  41. this.inherited(arguments);
  42. this.SvgG
  43. .attr("transform", "translate(" + this.target.margin.left + "," + this.target.margin.top + ")")
  44. ;
  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. function row(e) {
  62. var t = d3.select(this).selectAll(".cell").data(e.filter(function (e) {
  63. return e.z
  64. })).enter().append("rect").attr("class", "cell").attr("x", function (e) {
  65. return x(e.x)
  66. }).attr("width", x.rangeBand()).attr("height", x.rangeBand()).style("fill-opacity", function (e) {
  67. return z(e.z)
  68. }).style("fill", function (e) {
  69. return nodes[e.x].category == nodes[e.y].category ? c(nodes[e.x].category) : null
  70. }).on("mouseover", mouseover).on("mouseout", mouseout)
  71. }
  72. function mouseover(e) {
  73. d3.selectAll(".row text").classed("active", function (t, n) {
  74. return n == e.y
  75. });
  76. d3.selectAll(".column text").classed("active", function (t, n) {
  77. return n == e.x
  78. })
  79. }
  80. function mouseout() {
  81. d3.selectAll("text").classed("active", false)
  82. }
  83. function order(e) {
  84. x.domain(orders[e]);
  85. var t = this.SvgG.transition().duration(2500);
  86. t.selectAll(".row").delay(function (e, t) {
  87. return x(t) * 4
  88. }).attr("transform", function (e, t) {
  89. return "translate(0," + x(t) + ")"
  90. }).selectAll(".cell").delay(function (e) {
  91. return x(e.x) * 4
  92. }).attr("x", function (e) {
  93. return x(e.x)
  94. });
  95. t.selectAll(".column").delay(function (e, t) {
  96. return x(t) * 4
  97. }).attr("transform", function (e, t) {
  98. return "translate(" + x(t) + ")rotate(-90)"
  99. })
  100. }
  101. var width = Math.min(this.target.width, this.target.height) - this.target.margin.left - this.target.margin.right;
  102. var x = d3.scale.ordinal().rangeBands([0, width]), z = d3.scale.linear().domain([0, 4]).clamp(true), c = d3.scale.category10().domain(d3.range(10));
  103. var matrix = [];
  104. var nodes = vertices;
  105. var n = nodes.length;
  106. nodes.forEach(function (e, t) {
  107. e.index = t;
  108. e.count = 0;
  109. matrix[t] = d3.range(n).map(function (e) {
  110. return {
  111. x: e,
  112. y: t,
  113. z: 0
  114. }
  115. })
  116. });
  117. edges.forEach(function (e) {
  118. var d = matrix[e.source];
  119. var d1 = matrix[e.source][e.target];
  120. var d2 = matrix[e.source][e.target].z;
  121. matrix[e.source][e.target].z += e.weight;
  122. matrix[e.target][e.source].z += e.weight;
  123. matrix[e.source][e.source].z += e.weight;
  124. matrix[e.target][e.target].z += e.weight;
  125. nodes[e.source].count += e.weight;
  126. nodes[e.target].count += e.weight
  127. });
  128. var orders = {
  129. name: d3.range(n).sort(function (e, t) {
  130. return d3.ascending(nodes[e].label, nodes[t].label)
  131. }),
  132. count: d3.range(n).sort(function (e, t) {
  133. return nodes[t].count - nodes[e].count
  134. }),
  135. category: d3.range(n).sort(function (e, t) {
  136. return nodes[t].category - nodes[e].category
  137. })
  138. };
  139. x.domain(orders.category);
  140. this.SvgG.append("rect").attr("width", width).attr("height", width).style("fill", "#eee");
  141. var row = this.SvgG.selectAll(".row").data(matrix).enter().append("g").attr("class", "row").attr("transform", function (e, t) {
  142. return "translate(0," + x(t) + ")"
  143. }).each(row);
  144. row.append("line").attr("x2", width).style("stroke", "#fff");
  145. row.append("text").attr("x", -6).attr("y", x.rangeBand() / 2).attr("dy", ".32em").attr("text-anchor", "end").text(function (e, t) {
  146. return nodes[t].label
  147. });
  148. var column = this.SvgG.selectAll(".column").data(matrix).enter().append("g").attr("class", "column").attr("transform", function (e, t) {
  149. return "translate(" + x(t) + ")rotate(-90)"
  150. });
  151. column.append("line").attr("x1", -width).style("stroke", "#fff");
  152. column.append("text").attr("x", 6).attr("y", x.rangeBand() / 2).attr("dy", ".32em").attr("text-anchor", "start").text(function (e, t) {
  153. return nodes[t].label
  154. });
  155. }
  156. });
  157. });