agg_report.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. $(function () {
  2. function createImg(src) {
  3. var $img = $('<img />')
  4. $img.attr("src", src);
  5. $img.attr("class", "my-img-thumbnail pointer to-delete");
  6. $img.on("click", function (){
  7. showimage(src);
  8. });
  9. return $img;
  10. }
  11. $(".to-add").on("dragend", function (e) {
  12. var src = $(e.target).attr("src");
  13. if (images.indexOf(src) < 0) {
  14. images.push(src);
  15. var $img = createImg(src);
  16. $img.on("dragend", function (e) {
  17. var src = $(e.target).attr("src");
  18. var idx = images.indexOf(src);
  19. if (idx >= 0) {
  20. images.splice(idx, 1);
  21. }
  22. $(e.target).remove();
  23. });
  24. $("#new-report-img").append($img)
  25. }
  26. });
  27. $('.sup-collapse').click(function () {
  28. var dupTitle = $(this).parents('li').find('.sup-title');
  29. dupTitle.toggle();
  30. });
  31. //SVG
  32. var svg = d3.select("svg"),
  33. width = +svg.attr("width"),
  34. height = +svg.attr("height");
  35. var color = {
  36. 1: '#E36402',
  37. 2: '#1995CF',
  38. 6 : '#FFC000',
  39. 2.1: '#FFC000'
  40. // 1: '#CB8E01',
  41. // 2: '#7E511C',
  42. // // 2: '#1B80B2',
  43. // 2.1: '#1B80B2',
  44. // 6: '#9C4858'
  45. };
  46. var simulation = d3.forceSimulation()
  47. .force("link", d3.forceLink().id(function(d) { return d.id; }))
  48. .force("charge", d3.forceManyBody().strength(-200))
  49. .force("center", d3.forceCenter(width / 2 - 10, height / 2 - 20));
  50. var urlParams = new URLSearchParams(window.location.search);
  51. d3.json("/graph?masterId=" + urlParams.get("masterId"), function(error, graph) {
  52. if (error) throw error;
  53. var defs = svg.append("defs");
  54. var dropShadowFilter = defs.append('svg:filter')
  55. .attr('id', 'dropShadow')
  56. .attr('filterUnits', "userSpaceOnUse")
  57. .attr('width', '150%')
  58. .attr('height', '150%');
  59. dropShadowFilter.append('svg:feGaussianBlur')
  60. .attr('in', 'SourceGraphic')
  61. .attr('stdDeviation', 3)
  62. .attr('result', 'blur');
  63. // dropShadowFilter.append('svg:feColorMatrix')
  64. // .attr('in', 'blur-out')
  65. // .attr('type', 'hueRotate')
  66. // .attr('values', 30)
  67. // .attr('result', 'color-out');
  68. // dropShadowFilter.append('svg:feOffset')
  69. // .attr('in', 'color-out')
  70. // .attr('dx', 2)
  71. // .attr('dy', 2)
  72. // .attr('result', 'the-shadow');
  73. // dropShadowFilter.append('svg:feBlend')
  74. // .attr('in', 'SourceGraphic')
  75. // .attr('in2', 'the-shadow')
  76. // .attr('mode', 'normal');
  77. let link = svg.append("g")
  78. .attr("class", "links")
  79. .selectAll("line")
  80. .data(graph.links)
  81. .enter().append("line")
  82. .attr("stroke-width", function(d) { return Math.sqrt(d.value); });
  83. let node = svg.append("g")
  84. .attr("class", "nodes")
  85. .selectAll("g")
  86. .data(graph.nodes)
  87. .enter().append("g")
  88. .attr("class", "node")
  89. .on("mouseover", nodemouseover)
  90. .on("mouseout", nodemouseout)
  91. .on("click", nodeclick)
  92. .on("dblclick", nodedblclick);
  93. let circle = node.append("circle")
  94. .attr("r", function(d) { return 40/d.group; })
  95. .attr("fill", function(d) { return color[d.group]; })
  96. .style("stroke", function(d) { return color[d.group]; })
  97. .style("filter", "url(#dropShadow)")
  98. .call(d3.drag()
  99. .on("start", dragstarted)
  100. .on("drag", dragged)
  101. .on("end", dragended));
  102. let label = node.append("text")
  103. .attr("dy", ".35em")
  104. .text(function(d) { return d.name; });
  105. var marker = svg.append('marker')
  106. .attr('id', 'arrowhead')
  107. .attr('refX', 12) // Controls the shift of the arrow head along the path
  108. .attr('refY', 2)
  109. .attr('markerWidth', 6)
  110. .attr('markerHeight', 4)
  111. .attr('orient', 'auto')
  112. .attr('fill', '#509AE5')
  113. .append('path')
  114. .attr('d', 'M 0,0 V 4 L6,2 Z');
  115. link.attr('marker-end', 'url()');
  116. simulation
  117. .nodes(graph.nodes)
  118. .on("tick", ticked);
  119. simulation.force("link")
  120. .links(graph.links);
  121. function offsetEdge(d) {
  122. var sourceSize = 47/d.source.group;
  123. var targetSize = 47/d.target.group;
  124. var sourceCirc = sourceSize * 2 * Math.PI;
  125. var targetCirc = targetSize * 2 * Math.PI;
  126. var stRatio = sourceCirc/targetCirc;
  127. var diffX = d.target.y - d.source.y;
  128. var diffY = d.target.x - d.source.x;
  129. var angle0 = ( Math.atan2( diffY, diffX ) + ( Math.PI / 2 ) );
  130. var angle1 = angle0 + ( (Math.PI * 0.75) + (3 * 0.25) );
  131. var angle2 = angle0 + ( (Math.PI * 0.25) - (3 * 0.25) );
  132. var x1 = d.source.x + (sourceSize * Math.cos(angle1));
  133. var y1 = d.source.y - (sourceSize * Math.sin(angle1));
  134. var x2 = d.target.x + (targetSize * Math.cos(angle2));
  135. var y2 = d.target.y - (targetSize * Math.sin(angle2));
  136. return {x1: x1, y1: y1, x2: x2, y2: y2};
  137. }
  138. function ticked() {
  139. link
  140. .attr("x1", function(d) { return offsetEdge(d).x1; })
  141. .attr("y1", function(d) { return offsetEdge(d).y1; })
  142. .attr("x2", function(d) { return offsetEdge(d).x2; })
  143. .attr("y2", function(d) { return offsetEdge(d).y2; });
  144. circle
  145. .attr("cx", function(d) { return d.x; })
  146. .attr("cy", function(d) { return d.y; });
  147. label
  148. .attr("x", function(d) { return d.x + 8; })
  149. .attr("y", function(d) { return d.y; });
  150. }
  151. let linkedByIndex = {};
  152. graph.links.forEach((d) => {
  153. linkedByIndex[`${d.source.index},${d.target.index}`] = true;
  154. });
  155. function isConnected(a, b) {
  156. return isConnectedAsTarget(a, b) || isConnectedAsSource(a, b) || a.index === b.index;
  157. }
  158. function isConnectedAsSource(a, b) {
  159. return linkedByIndex[`${a.index},${b.index}`];
  160. }
  161. function isConnectedAsTarget(a, b) {
  162. return linkedByIndex[`${b.index},${a.index}`];
  163. }
  164. function isEqual(a, b) {
  165. return a.index === b.index;
  166. }
  167. function nodeclick(d) {
  168. circle.transition()
  169. .duration(750)
  170. .attr("r", function(d) { return 47/d.group; })
  171. .style("filter", null);
  172. node
  173. .transition(500)
  174. .style('opacity', o => {
  175. const isConnectedValue = isConnected(o, d);
  176. if (isConnectedValue) {
  177. return 1.0;
  178. }
  179. return 0.2;
  180. })
  181. .style("filter", o => {
  182. const isConnectedValue = isConnected(o, d);
  183. if (isConnectedValue) {
  184. return null;
  185. }
  186. return 'url(#dropShadow)';
  187. });
  188. link
  189. .transition(500)
  190. .style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : 0.2))
  191. .transition(500)
  192. .attr('marker-end', o => (o.source === d || o.target === d ? 'url(#arrowhead)' : 'url()'));
  193. $.get(
  194. d.href,
  195. function (data) {
  196. $('.detail-div').css('background-color', 'white');
  197. $('.detail-div').html(data);
  198. }
  199. )
  200. }
  201. function nodedblclick(d) {
  202. circle.transition()
  203. .duration(750)
  204. .attr("r", function(d) { return 47/d.group; })
  205. .style("filter", "url(#dropShadow)");
  206. node
  207. .transition(500)
  208. .style("filter", "url(#dropShadow)");
  209. link
  210. .transition(500);
  211. }
  212. function nodemouseover(d) {
  213. circle.transition()
  214. .duration(750)
  215. .attr("r", function(d) { return 55/d.group; });
  216. }
  217. function nodemouseout(d) {
  218. }
  219. });
  220. function dragstarted(d) {
  221. if (!d3.event.active) simulation.alphaTarget(0.3).restart();
  222. d.fx = d.x;
  223. d.fy = d.y;
  224. }
  225. function dragged(d) {
  226. d.fx = d3.event.x;
  227. d.fy = d3.event.y;
  228. }
  229. function dragended(d) {
  230. if (!d3.event.active) simulation.alphaTarget(0);
  231. d.fx = null;
  232. d.fy = null;
  233. }
  234. });