utility.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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, cb: (state: ScrollStateType) => void,
  11. ): ScrollStateType => {
  12. let rAF: number | null = null;
  13. const state = {
  14. right: true,
  15. down: true,
  16. lastX: viewAreaElement.scrollLeft,
  17. lastY: viewAreaElement.scrollTop,
  18. };
  19. const debounceScroll = (): void => {
  20. if (rAF) {
  21. return;
  22. }
  23. // schedule an invocation of scroll for next animation frame.
  24. rAF = window.requestAnimationFrame(() => {
  25. rAF = null;
  26. const currentX = viewAreaElement.scrollLeft;
  27. const { lastX } = state;
  28. if (currentX !== lastX) {
  29. state.right = currentX > lastX;
  30. }
  31. state.lastX = currentX;
  32. const currentY = viewAreaElement.scrollTop;
  33. const { lastY } = state;
  34. if (currentY !== lastY) {
  35. state.down = currentY > lastY;
  36. }
  37. state.lastY = currentY;
  38. cb(state);
  39. });
  40. };
  41. fromEvent(viewAreaElement, 'scroll').pipe(
  42. auditTime(300),
  43. throttleTime(200),
  44. ).subscribe(debounceScroll);
  45. return state;
  46. };
  47. export const scrollIntoView = (
  48. element: HTMLElement, spot?: {top: number}, skipOverflowHiddenElements = false,
  49. ): void => {
  50. let parent: HTMLElement = element.offsetParent as HTMLElement;
  51. let offsetY = element.offsetTop + element.clientTop;
  52. if (!parent) {
  53. return; // no need to scroll
  54. }
  55. while (
  56. (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth)
  57. || (skipOverflowHiddenElements && getComputedStyle(parent).overflow === 'hidden')
  58. ) {
  59. if (parent.dataset._scaleY) {
  60. offsetY /= parseInt(parent.dataset._scaleY, 10);
  61. }
  62. offsetY += parent.offsetTop;
  63. parent = parent.offsetParent as HTMLElement;
  64. if (!parent) {
  65. return; // no need to scroll
  66. }
  67. }
  68. if (spot) {
  69. if (spot.top !== undefined) {
  70. offsetY += spot.top;
  71. }
  72. }
  73. parent.scrollTop = offsetY;
  74. };
  75. export const scaleCheck = (scale: number): number => {
  76. if (typeof scale === 'number' && scale >= 50 && scale <= 250) {
  77. return Math.round(scale * 100) / 10000;
  78. }
  79. if (scale < 50) {
  80. return 0.5;
  81. }
  82. return 2.5;
  83. };