utility.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* eslint-disable no-underscore-dangle */
  2. import { fromEvent } from 'rxjs';
  3. import {
  4. auditTime,
  5. throttleTime,
  6. } from 'rxjs/operators';
  7. import { ScrollStateType } from '../constants/type';
  8. export const objIsEmpty = (obj: Record<string, any>): boolean => !Object.keys(obj).length;
  9. export const watchScroll = (
  10. viewAreaElement: HTMLElement | null, cb: (state: ScrollStateType) => void,
  11. ): ScrollStateType => {
  12. let rAF: number | null = null;
  13. const element = viewAreaElement as HTMLElement;
  14. const state = {
  15. right: true,
  16. down: true,
  17. lastX: element.scrollLeft,
  18. lastY: element.scrollTop,
  19. subscriber: {},
  20. };
  21. const debounceScroll = (): void => {
  22. if (rAF) {
  23. return;
  24. }
  25. // schedule an invocation of scroll for next animation frame.
  26. rAF = window.requestAnimationFrame(() => {
  27. rAF = null;
  28. const currentX = element.scrollLeft;
  29. const { lastX } = state;
  30. if (currentX !== lastX) {
  31. state.right = currentX > lastX;
  32. }
  33. state.lastX = currentX;
  34. const currentY = element.scrollTop;
  35. const { lastY } = state;
  36. if (currentY !== lastY) {
  37. state.down = currentY > lastY;
  38. }
  39. state.lastY = currentY;
  40. cb(state);
  41. });
  42. };
  43. const subscriber = fromEvent(element, 'scroll').pipe(
  44. throttleTime(200),
  45. auditTime(300),
  46. ).subscribe(debounceScroll);
  47. state.subscriber = subscriber;
  48. return state;
  49. };
  50. export const scrollIntoView = (
  51. element: HTMLElement, spot?: {top: number}, skipOverflowHiddenElements = false,
  52. ): void => {
  53. let parent: HTMLElement = element.offsetParent as HTMLElement;
  54. let offsetY = element.offsetTop + element.clientTop;
  55. if (!parent) {
  56. return; // no need to scroll
  57. }
  58. while (
  59. (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth)
  60. || (skipOverflowHiddenElements && getComputedStyle(parent).overflow === 'hidden')
  61. ) {
  62. if (parent.dataset._scaleY) {
  63. offsetY /= parseInt(parent.dataset._scaleY, 10);
  64. }
  65. offsetY += parent.offsetTop;
  66. parent = parent.offsetParent as HTMLElement;
  67. if (!parent) {
  68. return; // no need to scroll
  69. }
  70. }
  71. if (spot) {
  72. if (spot.top !== undefined) {
  73. offsetY += spot.top;
  74. }
  75. }
  76. parent.scrollTop = offsetY;
  77. };
  78. export const scaleCheck = (scale: number): number => {
  79. if (typeof scale === 'number' && scale >= 50 && scale <= 250) {
  80. return Math.round(scale * 100) / 10000;
  81. }
  82. if (scale < 50) {
  83. return 0.5;
  84. }
  85. return 2.5;
  86. };
  87. export const hexToRgb = (hex: string): any => {
  88. const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  89. return result ? {
  90. r: parseInt(result[1], 16),
  91. g: parseInt(result[2], 16),
  92. b: parseInt(result[3], 16),
  93. } : null;
  94. };
  95. export const downloadFileWithUri = (name: string, uri: string): void => {
  96. const ele = document.createElement('a');
  97. ele.download = name;
  98. ele.href = uri;
  99. document.body.appendChild(ele);
  100. ele.click();
  101. document.body.removeChild(ele);
  102. ele.remove();
  103. };