Chart/api/focus.ts

  1. /**
  2. * Copyright (c) 2017 ~ present NAVER Corp.
  3. * billboard.js project is licensed under the MIT license
  4. */
  5. import {select as d3Select} from "d3-selection";
  6. import {$FOCUS, $GAUGE} from "../../config/classes";
  7. type FocusParam = string | string[];
  8. export default {
  9. /**
  10. * This API highlights specified targets and fade out the others.<br><br>
  11. * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be highlighted.
  12. * @function focus
  13. * @instance
  14. * @memberof Chart
  15. * @param {string|Array} targetIdsValue Target ids to be highlighted.
  16. * @example
  17. * // data1 will be highlighted and the others will be faded out
  18. * chart.focus("data1");
  19. *
  20. * // data1 and data2 will be highlighted and the others will be faded out
  21. * chart.focus(["data1", "data2"]);
  22. *
  23. * // all targets will be highlighted
  24. * chart.focus();
  25. */
  26. focus(targetIdsValue?: FocusParam): void {
  27. const $$ = this.internal;
  28. const {state} = $$;
  29. const targetIds = $$.mapToTargetIds(targetIdsValue);
  30. const candidates = $$.$el.svg.selectAll(
  31. $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
  32. );
  33. this.revert();
  34. this.defocus();
  35. candidates.classed($FOCUS.focused, true).classed($FOCUS.defocused, false);
  36. if ($$.hasArcType() && !state.hasRadar) {
  37. $$.expandArc(targetIds);
  38. $$.hasType("gauge") &&
  39. $$.markOverlapped(targetIdsValue, $$, `.${$GAUGE.gaugeValue}`);
  40. }
  41. $$.toggleFocusLegend(targetIds, true);
  42. state.focusedTargetIds = targetIds;
  43. state.defocusedTargetIds = state.defocusedTargetIds.filter(id => targetIds.indexOf(id) < 0);
  44. },
  45. /**
  46. * This API fades out specified targets and reverts the others.<br><br>
  47. * You can specify multiple targets by giving an array that includes id as String. If no argument is given, all of targets will be faded out.
  48. * @function defocus
  49. * @instance
  50. * @memberof Chart
  51. * @param {string|Array} targetIdsValue Target ids to be faded out.
  52. * @example
  53. * // data1 will be faded out and the others will be reverted.
  54. * chart.defocus("data1");
  55. *
  56. * // data1 and data2 will be faded out and the others will be reverted.
  57. * chart.defocus(["data1", "data2"]);
  58. *
  59. * // all targets will be faded out.
  60. * chart.defocus();
  61. */
  62. defocus(targetIdsValue?: FocusParam): void {
  63. const $$ = this.internal;
  64. const {state} = $$;
  65. const targetIds = $$.mapToTargetIds(targetIdsValue);
  66. const candidates = $$.$el.svg.selectAll(
  67. $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
  68. );
  69. candidates.classed($FOCUS.focused, false).classed($FOCUS.defocused, true);
  70. if ($$.hasArcType(null, ["polar"])) {
  71. $$.unexpandArc(targetIds);
  72. $$.hasType("gauge") &&
  73. $$.undoMarkOverlapped($$, `.${$GAUGE.gaugeValue}`);
  74. }
  75. $$.toggleFocusLegend(targetIds, false);
  76. state.focusedTargetIds = state.focusedTargetIds.filter(id => targetIds.indexOf(id) < 0);
  77. state.defocusedTargetIds = targetIds;
  78. },
  79. /**
  80. * Revert focused or defocused state to initial state.<br><br>
  81. * You can specify multiple targets by giving an array that includes id as string. If no argument is given, all of targets will be reverted.
  82. * @function revert
  83. * @instance
  84. * @memberof Chart
  85. * @param {string|Array} targetIdsValue Target ids to be reverted
  86. * @example
  87. * // 'data1' will be reverted.
  88. * chart.revert("data1");
  89. *
  90. * // 'data1' and 'data2' will be reverted.
  91. * chart.revert(["data1", "data2"]);
  92. *
  93. * // all targets will be reverted.
  94. * chart.revert();
  95. */
  96. revert(targetIdsValue?: FocusParam): void {
  97. const $$ = this.internal;
  98. const {config, state, $el} = $$;
  99. const targetIds = $$.mapToTargetIds(targetIdsValue);
  100. const candidates = $el.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets
  101. candidates.classed($FOCUS.focused, false).classed($FOCUS.defocused, false);
  102. $$.hasArcType(null, ["polar"]) && $$.unexpandArc(targetIds);
  103. if (config.legend_show) {
  104. $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
  105. $el.legend.selectAll($$.selectorLegends(targetIds))
  106. .filter(function() {
  107. return d3Select(this).classed($FOCUS.legendItemFocused);
  108. })
  109. .classed($FOCUS.legendItemFocused, false);
  110. }
  111. state.focusedTargetIds = [];
  112. state.defocusedTargetIds = [];
  113. }
  114. };