Chart/api/subchart.ts

  1. /**
  2. * Copyright (c) 2017 ~ present NAVER Corp.
  3. * billboard.js project is licensed under the MIT license
  4. */
  5. import type {TDomain} from "../../ChartInternal/data/IData";
  6. import {$COMMON} from "../../config/classes";
  7. import {extend, parseDate} from "../../module/util";
  8. /**
  9. * Select subchart by giving x domain range.
  10. * - **ℹ️ NOTE:**
  11. * - Due to the limitations of floating point precision, domain value may not be exact returning approximately values.
  12. * @function subchart
  13. * @instance
  14. * @memberof Chart
  15. * @param {Array} domainValue If domain range is given, the subchart will be seleted to the given domain. If no argument is given, the current subchart selection domain will be returned.
  16. * @returns {Array} domain value in array
  17. * @example
  18. * // Specify domain for subchart selection
  19. * chart.subchart([1, 2]);
  20. *
  21. * // Get the current subchart selection domain range
  22. * // Domain value may not be exact returning approximately values.
  23. * chart.subchart();
  24. */
  25. // NOTE: declared funciton assigning to variable to prevent duplicated method generation in JSDoc.
  26. const subchart = function<T = TDomain[]>(domainValue?: T): T | undefined {
  27. const $$ = this.internal;
  28. const {axis, brush, config, scale: {x, subX}, state} = $$;
  29. let domain;
  30. if (config.subchart_show) {
  31. domain = domainValue;
  32. if (Array.isArray(domain)) {
  33. if (axis.isTimeSeries()) {
  34. domain = domain.map(x => parseDate.bind($$)(x));
  35. }
  36. const isWithinRange = $$.withinRange(
  37. domain,
  38. $$.getZoomDomain("subX", true),
  39. $$.getZoomDomain("subX")
  40. );
  41. if (isWithinRange) {
  42. state.domain = domain;
  43. brush.move(
  44. brush.getSelection(),
  45. domain.map(subX)
  46. );
  47. }
  48. } else {
  49. domain = state.domain ?? x.orgDomain();
  50. }
  51. }
  52. return domain as T;
  53. };
  54. extend(subchart, {
  55. /**
  56. * Show subchart
  57. * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
  58. * @function subchart․show
  59. * @instance
  60. * @memberof Chart
  61. * @example
  62. * // for ESM imports, needs to import 'subchart' and must be instantiated first to enable subchart's API.
  63. * import {subchart} from "billboard.js";
  64. *
  65. * const chart = bb.generate({
  66. * ...
  67. * subchart: {
  68. * // need to be instantiated by calling 'subchart()'
  69. * enabled: subchart()
  70. *
  71. * // in case don't want subchart to be shown at initialization, instantiate with '!subchart()'
  72. * enabled: !subchart()
  73. * }
  74. * });
  75. *
  76. * chart.subchart.show();
  77. */
  78. show(): void {
  79. const $$ = this.internal;
  80. const {$el: {subchart}, config} = $$;
  81. const show = config.subchart_show;
  82. if (!show) {
  83. // unbind zoom event bound to chart rect area
  84. $$.unbindZoomEvent();
  85. config.subchart_show = !show;
  86. !subchart.main && $$.initSubchart();
  87. let $target = subchart.main.selectAll(`.${$COMMON.target}`);
  88. // need to cover when new data has been loaded
  89. if ($$.data.targets.length !== $target.size()) {
  90. $$.updateSizes();
  91. $$.updateTargetsForSubchart($$.data.targets);
  92. $target = subchart.main?.selectAll(`.${$COMMON.target}`);
  93. }
  94. $target?.style("opacity", null);
  95. subchart.main?.style("display", null);
  96. this.resize();
  97. }
  98. },
  99. /**
  100. * Hide generated subchart
  101. * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
  102. * @function subchart․hide
  103. * @instance
  104. * @memberof Chart
  105. * @example
  106. * chart.subchart.hide();
  107. */
  108. hide(): void {
  109. const $$ = this.internal;
  110. const {$el: {subchart: {main}}, config} = $$;
  111. if (config.subchart_show && main?.style("display") !== "none") {
  112. config.subchart_show = false;
  113. main.style("display", "none");
  114. this.resize();
  115. }
  116. },
  117. /**
  118. * Toggle the visiblity of subchart
  119. * - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
  120. * @function subchart․toggle
  121. * @instance
  122. * @memberof Chart
  123. * @example
  124. * // When subchart is hidden, will be shown
  125. * // When subchart is shown, will be hidden
  126. * chart.subchart.toggle();
  127. */
  128. toggle(): void {
  129. const $$ = this.internal;
  130. const {config} = $$;
  131. this.subchart[config.subchart_show ? "hide" : "show"]();
  132. },
  133. /**
  134. * Reset subchart selection
  135. * @function subchart․reset
  136. * @instance
  137. * @memberof Chart
  138. * @example
  139. * // Reset subchart selection
  140. * chart.subchart.reset();
  141. */
  142. reset(): void {
  143. const $$ = this.internal;
  144. const {brush} = $$;
  145. brush.clear(brush.getSelection());
  146. }
  147. });
  148. export default {
  149. subchart
  150. };