Source

modules/d3/charts/graph.chart.js

  1. const {
  2. d3,
  3. drag,
  4. color,
  5. addTitleNode,
  6. addTitleArch,
  7. addArchFunctions,
  8. addNodeFunctions,
  9. appendChart
  10. } = require('../others/d3.graphCharts.utils');
  11. /**
  12. * @memberOf D3Module
  13. * @function
  14. * @name graphChart
  15. * @desc function for create a graph chart
  16. * @param {HTMLBodyElement} htmlElementContainer - container html element, where the chart is inserted
  17. * @param {string} idElement - chart id
  18. * @param {object} data - data to be plotted within the chart, with the structure:
  19. * <code>{
  20. * nodes: [{ id: string, group: number }],
  21. * arches: [{ source: string, target: string, value: object, ... }]
  22. * }</code>
  23. * @param {array=} [nodeFunctions=[]] - functions of each node within the chart, with the structure:
  24. * <code>nodeFunctions: [{ event: string // event type, handler: function(node?) // action to take }]</code>
  25. * @param {array=} [archesFunctions=[]] - functions of each arch within the chart, with the structure:
  26. * <code>archesFunctions: [{ event: string // event type, handler: function(arch?) // action to take }]</code>
  27. * @param {number=} [width=500] - chart width inside the container
  28. * @param {number=} [height=500] - chart height inside the container
  29. * @param {string=} [backgroundColor='white'] - background color for the chart
  30. * @see <img src="https://i.imgur.com/byHuczW.jpg"></img>
  31. * @example D3.graphChart(
  32. * document.getElementById('charts'),
  33. * 'graph_chart',
  34. * {
  35. * nodes: [
  36. * { id: 'Armenia', group: 1 },
  37. * { id: 'Calarca', group: 1 },
  38. * { id: 'Circasia', group: 1 },
  39. * { id: 'Pereira', group: 2 },
  40. * { id: 'Cali', group: 3 },
  41. * { id: 'Bogota', group: 4 },
  42. * { id: 'Soacha', group: 4 },
  43. * { id: 'Medellin', group: 5 },
  44. * { id: 'Itagui', group: 5 },
  45. * { id: 'Envigado', group: 5 }
  46. * ],
  47. * arches: [
  48. * { source: 'Armenia', target: 'Calarca', value: 5 },
  49. * { source: 'Armenia', target: 'Circasia', value: 5 },
  50. * { source: 'Cali', target: 'Medellin', value: 5 },
  51. * { source: 'Medellin', target: 'Itagui', value: 5 },
  52. * { source: 'Armenia', target: 'Medellin', value: 5 },
  53. * { source: 'Cali', target: 'Bogota', value: 5 },
  54. * { source: 'Bogota', target: 'Soacha', value: 5 },
  55. * { source: 'Armenia', target: 'Bogota', value: 5 },
  56. * { source: 'Medellin', target: 'Envigado', value: 5 },
  57. * { source: 'Armenia', target: 'Pereira', value: 5 }
  58. * ]
  59. * }
  60. * );
  61. */
  62. module.exports = (
  63. htmlElementContainer,
  64. idElement,
  65. data,
  66. nodeFunctions = [],
  67. archesFunctions = [],
  68. width = 500,
  69. height = 500,
  70. backgroundColor = 'white'
  71. ) => {
  72. const svg = d3.create('svg')
  73. .attr('height', height)
  74. .attr('width', width)
  75. .style('background-color', backgroundColor);
  76. const links = data.arches.map(d => Object.create(d));
  77. const nodes = data.nodes.map(d => Object.create(d));
  78. const simulation = d3.forceSimulation(nodes)
  79. .force('link', d3.forceLink(links).id(d => d.id))
  80. .force('charge', d3.forceManyBody())
  81. .force('center', d3.forceCenter(width / 2, height / 2));
  82. const link = svg.append('g')
  83. .attr('stroke', '#999')
  84. .attr('stroke-opacity', 0.6)
  85. .selectAll('line')
  86. .data(links)
  87. .join('line')
  88. .attr('stroke-width', d => Math.sqrt(d.value));
  89. const node = svg.append('g')
  90. .attr('stroke', '#fff')
  91. .attr('stroke-width', 1.5)
  92. .selectAll('circle')
  93. .data(nodes)
  94. .join('circle')
  95. .attr('r', 5)
  96. .attr('fill', color())
  97. .call(drag(simulation));
  98. addTitleArch(link, data);
  99. addTitleNode(node);
  100. addNodeFunctions(nodeFunctions, node, data);
  101. addArchFunctions(archesFunctions, link, data);
  102. simulation.on('tick', () => {
  103. link.attr('x1', d => d.source.x)
  104. .attr('y1', d => d.source.y)
  105. .attr('x2', d => d.target.x)
  106. .attr('y2', d => d.target.y);
  107. node.attr('cx', d => d.x)
  108. .attr('cy', d => d.y);
  109. });
  110. appendChart(svg, idElement, htmlElementContainer);
  111. };