Stats.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import React from "react";
  2. import { getCommonBounds } from "../element/bounds";
  3. import { NonDeletedExcalidrawElement } from "../element/types";
  4. import { t } from "../i18n";
  5. import { getTargetElements } from "../scene";
  6. import { AppState, ExcalidrawProps } from "../types";
  7. import { CloseIcon } from "./icons";
  8. import { Island } from "./Island";
  9. import "./Stats.scss";
  10. export const Stats = (props: {
  11. appState: AppState;
  12. setAppState: React.Component<any, AppState>["setState"];
  13. elements: readonly NonDeletedExcalidrawElement[];
  14. onClose: () => void;
  15. renderCustomStats: ExcalidrawProps["renderCustomStats"];
  16. }) => {
  17. const boundingBox = getCommonBounds(props.elements);
  18. const selectedElements = getTargetElements(props.elements, props.appState);
  19. const selectedBoundingBox = getCommonBounds(selectedElements);
  20. return (
  21. <div className="Stats">
  22. <Island padding={2}>
  23. <div className="close" onClick={props.onClose}>
  24. {CloseIcon}
  25. </div>
  26. <h3>{t("stats.title")}</h3>
  27. <table>
  28. <tbody>
  29. <tr>
  30. <th colSpan={2}>{t("stats.scene")}</th>
  31. </tr>
  32. <tr>
  33. <td>{t("stats.elements")}</td>
  34. <td>{props.elements.length}</td>
  35. </tr>
  36. <tr>
  37. <td>{t("stats.width")}</td>
  38. <td>{Math.round(boundingBox[2]) - Math.round(boundingBox[0])}</td>
  39. </tr>
  40. <tr>
  41. <td>{t("stats.height")}</td>
  42. <td>{Math.round(boundingBox[3]) - Math.round(boundingBox[1])}</td>
  43. </tr>
  44. {selectedElements.length === 1 && (
  45. <tr>
  46. <th colSpan={2}>{t("stats.element")}</th>
  47. </tr>
  48. )}
  49. {selectedElements.length > 1 && (
  50. <>
  51. <tr>
  52. <th colSpan={2}>{t("stats.selected")}</th>
  53. </tr>
  54. <tr>
  55. <td>{t("stats.elements")}</td>
  56. <td>{selectedElements.length}</td>
  57. </tr>
  58. </>
  59. )}
  60. {selectedElements.length > 0 && (
  61. <>
  62. <tr>
  63. <td>{"x"}</td>
  64. <td>{Math.round(selectedBoundingBox[0])}</td>
  65. </tr>
  66. <tr>
  67. <td>{"y"}</td>
  68. <td>{Math.round(selectedBoundingBox[1])}</td>
  69. </tr>
  70. <tr>
  71. <td>{t("stats.width")}</td>
  72. <td>
  73. {Math.round(
  74. selectedBoundingBox[2] - selectedBoundingBox[0],
  75. )}
  76. </td>
  77. </tr>
  78. <tr>
  79. <td>{t("stats.height")}</td>
  80. <td>
  81. {Math.round(
  82. selectedBoundingBox[3] - selectedBoundingBox[1],
  83. )}
  84. </td>
  85. </tr>
  86. </>
  87. )}
  88. {selectedElements.length === 1 && (
  89. <tr>
  90. <td>{t("stats.angle")}</td>
  91. <td>
  92. {`${Math.round(
  93. (selectedElements[0].angle * 180) / Math.PI,
  94. )}°`}
  95. </td>
  96. </tr>
  97. )}
  98. {props.renderCustomStats?.(props.elements, props.appState)}
  99. </tbody>
  100. </table>
  101. </Island>
  102. </div>
  103. );
  104. };