chart/crosshairPlot.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 Crosshair Plot (Experimental) Chart
  7. *
  8. * @module
  9. *
  10. * @example
  11. * let chartHolder = d3.select("#chartholder");
  12. *
  13. * let myData = [...];
  14. *
  15. * let myChart = d3.x3d.chart.crosshairPlot();
  16. *
  17. * chartHolder.datum(myData).call(myChart);
  18. */
  19. export default function() {
  20. /* Default Properties */
  21. let width = 500;
  22. let height = 500;
  23. let dimensions = { x: 40, y: 40, z: 40 };
  24. let classed = "d3X3dCrosshairPlot";
  25. let debug = false;
  26. /* Scales */
  27. let xScale;
  28. let yScale;
  29. let zScale;
  30. /* Components */
  31. const viewpoint = component.viewpoint();
  32. const axis = component.axisThreePlane();
  33. const crosshair = component.crosshair();
  34. /**
  35. * Initialise Data and Scales
  36. *
  37. * @private
  38. * @param {Array} data - Chart data.
  39. */
  40. const init = function(data) {
  41. const { coordinatesMax } = dataTransform(data).summary();
  42. const { x: maxX, y: maxY, z: maxZ } = coordinatesMax;
  43. const { x: dimensionX, y: dimensionY, z: dimensionZ } = dimensions;
  44. xScale = d3.scaleLinear()
  45. .domain([0, maxX])
  46. .range([0, dimensionX]);
  47. yScale = d3.scaleLinear()
  48. .domain([0, maxY])
  49. .range([0, dimensionY]);
  50. zScale = d3.scaleLinear()
  51. .domain([0, maxZ])
  52. .range([0, dimensionZ]);
  53. };
  54. /**
  55. * Constructor
  56. *
  57. * @constructor
  58. * @alias crosshairPlot
  59. * @param {d3.selection} selection - The chart holder D3 selection.
  60. */
  61. const my = function(selection) {
  62. const layers = ["axis", "crosshairs"];
  63. const scene = createScene(selection, layers, classed, width, height, debug);
  64. selection.each((data) => {
  65. init(data);
  66. // Add Viewpoint
  67. viewpoint.centerOfRotation([dimensions.x / 2, dimensions.y / 2, dimensions.z / 2]);
  68. scene.call(viewpoint);
  69. // Add Axis
  70. axis.xScale(xScale)
  71. .yScale(yScale)
  72. .zScale(zScale)
  73. .dimensions(dimensions);
  74. scene.select(".axis")
  75. .call(axis);
  76. // Add Crosshair
  77. crosshair.xScale(xScale)
  78. .yScale(yScale)
  79. .zScale(zScale);
  80. let crosshairs = scene.select(".crosshairs")
  81. .datum(data)
  82. .selectAll(".crosshair")
  83. .data((d) => d.values);
  84. crosshairs.enter()
  85. .append("group")
  86. .classed("crosshair", true)
  87. .merge(crosshairs)
  88. .transition()
  89. .each(function() {
  90. d3.select(this).call(crosshair);
  91. });
  92. });
  93. };
  94. /**
  95. * Width Getter / Setter
  96. *
  97. * @param {number} _v - X3D canvas width in px.
  98. * @returns {*}
  99. */
  100. my.width = function(_v) {
  101. if (!arguments.length) return width;
  102. width = _v;
  103. return this;
  104. };
  105. /**
  106. * Height Getter / Setter
  107. *
  108. * @param {number} _v - X3D canvas height in px.
  109. * @returns {*}
  110. */
  111. my.height = function(_v) {
  112. if (!arguments.length) return height;
  113. height = _v;
  114. return this;
  115. };
  116. /**
  117. * Dimensions Getter / Setter
  118. *
  119. * @param {{x: number, y: number, z: number}} _v - 3D object dimensions.
  120. * @returns {*}
  121. */
  122. my.dimensions = function(_v) {
  123. if (!arguments.length) return dimensions;
  124. dimensions = _v;
  125. return this;
  126. };
  127. /**
  128. * X Scale Getter / Setter
  129. *
  130. * @param {d3.scale} _v - D3 scale.
  131. * @returns {*}
  132. */
  133. my.xScale = function(_v) {
  134. if (!arguments.length) return xScale;
  135. xScale = _v;
  136. return my;
  137. };
  138. /**
  139. * Y Scale Getter / Setter
  140. *
  141. * @param {d3.scale} _v - D3 scale.
  142. * @returns {*}
  143. */
  144. my.yScale = function(_v) {
  145. if (!arguments.length) return yScale;
  146. yScale = _v;
  147. return my;
  148. };
  149. /**
  150. * Z Scale Getter / Setter
  151. *
  152. * @param {d3.scale} _v - D3 scale.
  153. * @returns {*}
  154. */
  155. my.zScale = function(_v) {
  156. if (!arguments.length) return zScale;
  157. zScale = _v;
  158. return my;
  159. };
  160. /**
  161. * Debug Getter / Setter
  162. *
  163. * @param {boolean} _v - Show debug log and stats. True/False.
  164. * @returns {*}
  165. */
  166. my.debug = function(_v) {
  167. if (!arguments.length) return debug;
  168. debug = _v;
  169. return my;
  170. };
  171. return my;
  172. }