utils.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. export const SVG_NS = "http://www.w3.org/2000/svg";
  2. export function getDateTime() {
  3. const date = new Date();
  4. const year = date.getFullYear();
  5. const month = date.getMonth() + 1;
  6. const day = date.getDate();
  7. const hr = date.getHours();
  8. const min = date.getMinutes();
  9. const secs = date.getSeconds();
  10. return `${year}${month}${day}${hr}${min}${secs}`;
  11. }
  12. export function capitalizeString(str: string) {
  13. return str.charAt(0).toUpperCase() + str.slice(1);
  14. }
  15. export function isToolIcon(
  16. target: Element | EventTarget | null,
  17. ): target is HTMLElement {
  18. return target instanceof HTMLElement && target.className.includes("ToolIcon");
  19. }
  20. export function isInputLike(
  21. target: Element | EventTarget | null,
  22. ): target is
  23. | HTMLInputElement
  24. | HTMLTextAreaElement
  25. | HTMLSelectElement
  26. | HTMLBRElement
  27. | HTMLDivElement {
  28. return (
  29. (target instanceof HTMLElement && target.dataset.type === "wysiwyg") ||
  30. target instanceof HTMLBRElement || // newline in wysiwyg
  31. target instanceof HTMLInputElement ||
  32. target instanceof HTMLTextAreaElement ||
  33. target instanceof HTMLSelectElement
  34. );
  35. }
  36. export function isWritableElement(
  37. target: Element | EventTarget | null,
  38. ): target is
  39. | HTMLInputElement
  40. | HTMLTextAreaElement
  41. | HTMLBRElement
  42. | HTMLDivElement {
  43. return (
  44. (target instanceof HTMLElement && target.dataset.type === "wysiwyg") ||
  45. target instanceof HTMLBRElement || // newline in wysiwyg
  46. target instanceof HTMLTextAreaElement ||
  47. (target instanceof HTMLInputElement &&
  48. (target.type === "text" || target.type === "number"))
  49. );
  50. }
  51. // https://github.com/grassator/canvas-text-editor/blob/master/lib/FontMetrics.js
  52. export function measureText(text: string, font: string) {
  53. const line = document.createElement("div");
  54. const body = document.body;
  55. line.style.position = "absolute";
  56. line.style.whiteSpace = "nowrap";
  57. line.style.font = font;
  58. body.appendChild(line);
  59. // Now we can measure width and height of the letter
  60. line.innerText = text;
  61. const width = line.offsetWidth;
  62. const height = line.offsetHeight;
  63. // Now creating 1px sized item that will be aligned to baseline
  64. // to calculate baseline shift
  65. const span = document.createElement("span");
  66. span.style.display = "inline-block";
  67. span.style.overflow = "hidden";
  68. span.style.width = "1px";
  69. span.style.height = "1px";
  70. line.appendChild(span);
  71. // Baseline is important for positioning text on canvas
  72. const baseline = span.offsetTop + span.offsetHeight;
  73. document.body.removeChild(line);
  74. return { width, height, baseline };
  75. }
  76. export function debounce<T extends any[]>(
  77. fn: (...args: T) => void,
  78. timeout: number,
  79. ) {
  80. let handle = 0;
  81. let lastArgs: T;
  82. const ret = (...args: T) => {
  83. lastArgs = args;
  84. clearTimeout(handle);
  85. handle = window.setTimeout(() => fn(...args), timeout);
  86. };
  87. ret.flush = () => {
  88. clearTimeout(handle);
  89. fn(...lastArgs);
  90. };
  91. return ret;
  92. }
  93. export function selectNode(node: Element) {
  94. const selection = window.getSelection();
  95. if (selection) {
  96. const range = document.createRange();
  97. range.selectNodeContents(node);
  98. selection.removeAllRanges();
  99. selection.addRange(range);
  100. }
  101. }
  102. export function removeSelection() {
  103. const selection = window.getSelection();
  104. if (selection) {
  105. selection.removeAllRanges();
  106. }
  107. }
  108. export function distance(x: number, y: number) {
  109. return Math.abs(x - y);
  110. }
  111. export function distance2d(x1: number, y1: number, x2: number, y2: number) {
  112. const xd = x2 - x1;
  113. const yd = y2 - y1;
  114. return Math.sqrt(xd * xd + yd * yd);
  115. }