chart/heatMap.js

  1. import * as d3 from "d3";
  2. import dataTransform from "../dataTransform.js";
  3. import component from "../component.js";
  4. import { createScene } from "../base.js";
  5. /**
  6. * Reusable 3D Heat Map
  7. *
  8. * @module
  9. *
  10. * @example
  11. * let chartHolder = d3.select("#chartholder");
  12. *
  13. * let myData = [...];
  14. *
  15. * let myChart = d3.x3d.chart.heatMap();
  16. *
  17. * chartHolder.datum(myData).call(myChart);
  18. *
  19. * @see https://datavizproject.com/data-type/heat-map/
  20. */
  21. export default function() {
  22. /* Default Properties */
  23. let width = 500;
  24. let height = 500;
  25. let dimensions = { x: 40, y: 20, z: 40 };
  26. let colors = ["#1e253f", "#e33b30"];
  27. let classed = "d3X3dHeatMap";
  28. let labelPosition = "distal";
  29. let debug = false;
  30. /* Scales */
  31. let xScale;
  32. let yScale;
  33. let zScale;
  34. let colorScale;
  35. /* Components */
  36. const viewpoint = component.viewpoint();
  37. const axis = component.axisThreePlane();
  38. const bars = component.heatMap();
  39. const light = component.light();
  40. /**
  41. * Initialise Data and Scales
  42. *
  43. * @private
  44. * @param {Array} data - Chart data.
  45. */
  46. const init = function(data) {
  47. const { rowKeys, columnKeys, valueMax } = dataTransform(data).summary();
  48. const valueExtent = [0, valueMax];
  49. const { x: dimensionX, y: dimensionY, z: dimensionZ } = dimensions;
  50. xScale = d3.scaleBand()
  51. .domain(columnKeys)
  52. .range([0, dimensionX])
  53. .paddingOuter(0.5)
  54. .paddingInner(0.1)
  55. .align(1);
  56. yScale = d3.scaleLinear()
  57. .domain(valueExtent)
  58. .range([0, dimensionY])
  59. .nice();
  60. zScale = d3.scaleBand()
  61. .domain(rowKeys.reverse())
  62. .range([0, dimensionZ])
  63. .paddingOuter(0.5)
  64. .paddingInner(0.1)
  65. .align(1);
  66. colorScale = d3.scaleLinear()
  67. .domain(valueExtent)
  68. .range(colors);
  69. };
  70. /**
  71. * Constructor
  72. *
  73. * @constructor
  74. * @alias heatMap
  75. * @param {d3.selection} selection - The chart holder D3 selection.
  76. */
  77. const my = function(selection) {
  78. const layers = ["axis", "bars"];
  79. const scene = createScene(selection, layers, classed, width, height, debug);
  80. selection.each((data) => {
  81. init(data);
  82. // Add Viewpoint
  83. viewpoint.centerOfRotation([dimensions.x / 2, dimensions.y / 2, dimensions.z / 2]);
  84. scene.call(viewpoint);
  85. // Add Axis
  86. axis.xScale(xScale)
  87. .yScale(yScale)
  88. .zScale(zScale)
  89. .labelPosition(labelPosition);
  90. scene.select(".axis")
  91. .call(axis);
  92. // Add Bars
  93. bars.xScale(xScale)
  94. .yScale(yScale)
  95. .zScale(zScale)
  96. .colors(colors);
  97. scene.select(".bars")
  98. .datum(data)
  99. .call(bars);
  100. // Add Light
  101. scene.call(light);
  102. });
  103. };
  104. /**
  105. * Width Getter / Setter
  106. *
  107. * @param {number} _v - X3D canvas width in px.
  108. * @returns {*}
  109. */
  110. my.width = function(_v) {
  111. if (!arguments.length) return width;
  112. width = _v;
  113. return this;
  114. };
  115. /**
  116. * Height Getter / Setter
  117. *
  118. * @param {number} _v - X3D canvas height in px.
  119. * @returns {*}
  120. */
  121. my.height = function(_v) {
  122. if (!arguments.length) return height;
  123. height = _v;
  124. return this;
  125. };
  126. /**
  127. * Dimensions Getter / Setter
  128. *
  129. * @param {{x: number, y: number, z: number}} _v - 3D object dimensions.
  130. * @returns {*}
  131. */
  132. my.dimensions = function(_v) {
  133. if (!arguments.length) return dimensions;
  134. dimensions = _v;
  135. return this;
  136. };
  137. /**
  138. * X Scale Getter / Setter
  139. *
  140. * @param {d3.scale} _v - D3 scale.
  141. * @returns {*}
  142. */
  143. my.xScale = function(_v) {
  144. if (!arguments.length) return xScale;
  145. xScale = _v;
  146. return my;
  147. };
  148. /**
  149. * Y Scale Getter / Setter
  150. *
  151. * @param {d3.scale} _v - D3 scale.
  152. * @returns {*}
  153. */
  154. my.yScale = function(_v) {
  155. if (!arguments.length) return yScale;
  156. yScale = _v;
  157. return my;
  158. };
  159. /**
  160. * Z Scale Getter / Setter
  161. *
  162. * @param {d3.scale} _v - D3 scale.
  163. * @returns {*}
  164. */
  165. my.zScale = function(_v) {
  166. if (!arguments.length) return zScale;
  167. zScale = _v;
  168. return my;
  169. };
  170. /**
  171. * Color Scale Getter / Setter
  172. *
  173. * @param {d3.scale} _v - D3 color scale.
  174. * @returns {*}
  175. */
  176. my.colorScale = function(_v) {
  177. if (!arguments.length) return colorScale;
  178. colorScale = _v;
  179. return my;
  180. };
  181. /**
  182. * Colors Getter / Setter
  183. *
  184. * @param {Array} _v - Array of colours used by color scale.
  185. * @returns {*}
  186. */
  187. my.colors = function(_v) {
  188. if (!arguments.length) return colors;
  189. colors = _v;
  190. return my;
  191. };
  192. /**
  193. * Label Position Getter / Setter
  194. *
  195. * @param {string} _v - Position ("proximal" or "distal")
  196. * @returns {*}
  197. */
  198. my.labelPosition = function(_v) {
  199. if (!arguments.length) return labelPosition;
  200. labelPosition = _v;
  201. return my;
  202. };
  203. /**
  204. * Debug Getter / Setter
  205. *
  206. * @param {boolean} _v - Show debug log and stats. True/False.
  207. * @returns {*}
  208. */
  209. my.debug = function(_v) {
  210. if (!arguments.length) return debug;
  211. debug = _v;
  212. return my;
  213. };
  214. return my;
  215. }