utility.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. };
  20. const debounceScroll = (): void => {
  21. if (rAF) {
  22. return;
  23. }
  24. // schedule an invocation of scroll for next animation frame.
  25. rAF = window.requestAnimationFrame(() => {
  26. rAF = null;
  27. const currentX = element.scrollLeft;
  28. const { lastX } = state;
  29. if (currentX !== lastX) {
  30. state.right = currentX > lastX;
  31. }
  32. state.lastX = currentX;
  33. const currentY = element.scrollTop;
  34. const { lastY } = state;
  35. if (currentY !== lastY) {
  36. state.down = currentY > lastY;
  37. }
  38. state.lastY = currentY;
  39. cb(state);
  40. });
  41. };
  42. fromEvent(element, 'scroll').pipe(
  43. throttleTime(200),
  44. auditTime(300),
  45. ).subscribe(debounceScroll);
  46. return state;
  47. };
  48. export const scrollIntoView = (
  49. element: HTMLElement, spot?: {top: number}, skipOverflowHiddenElements = false,
  50. ): void => {
  51. let parent: HTMLElement = element.offsetParent as HTMLElement;
  52. let offsetY = element.offsetTop + element.clientTop;
  53. if (!parent) {
  54. return; // no need to scroll
  55. }
  56. while (
  57. (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth)
  58. || (skipOverflowHiddenElements && getComputedStyle(parent).overflow === 'hidden')
  59. ) {
  60. if (parent.dataset._scaleY) {
  61. offsetY /= parseInt(parent.dataset._scaleY, 10);
  62. }
  63. offsetY += parent.offsetTop;
  64. parent = parent.offsetParent as HTMLElement;
  65. if (!parent) {
  66. return; // no need to scroll
  67. }
  68. }
  69. if (spot) {
  70. if (spot.top !== undefined) {
  71. offsetY += spot.top;
  72. }
  73. }
  74. parent.scrollTop = offsetY;
  75. };
  76. export const scaleCheck = (scale: number): number => {
  77. if (typeof scale === 'number' && scale >= 50 && scale <= 250) {
  78. return Math.round(scale * 100) / 10000;
  79. }
  80. if (scale < 50) {
  81. return 0.5;
  82. }
  83. return 2.5;
  84. };
  85. export const hexToRgb = (hex: string): any => {
  86. const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  87. return result ? {
  88. r: parseInt(result[1], 16),
  89. g: parseInt(result[2], 16),
  90. b: parseInt(result[3], 16),
  91. } : null;
  92. };
  93. export const chunk = (arr: any[], chunkSize: number): any[] => {
  94. const R = [];
  95. for (let i = 0, len = arr.length; i < len; i += chunkSize) {
  96. R.push(arr.slice(i, i + chunkSize));
  97. }
  98. return R;
  99. };