useFrameWheel.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import raf from "rc-util/es/raf";
  2. import { useRef } from 'react';
  3. import isFF from "../utils/isFirefox";
  4. import useOriginScroll from "./useOriginScroll";
  5. export default function useFrameWheel(inVirtual, isScrollAtTop, isScrollAtBottom, isScrollAtLeft, isScrollAtRight, horizontalScroll,
  6. /***
  7. * Return `true` when you need to prevent default event
  8. */
  9. onWheelDelta) {
  10. var offsetRef = useRef(0);
  11. var nextFrameRef = useRef(null);
  12. // Firefox patch
  13. var wheelValueRef = useRef(null);
  14. var isMouseScrollRef = useRef(false);
  15. // Scroll status sync
  16. var originScroll = useOriginScroll(isScrollAtTop, isScrollAtBottom, isScrollAtLeft, isScrollAtRight);
  17. function onWheelY(e, deltaY) {
  18. raf.cancel(nextFrameRef.current);
  19. // Do nothing when scroll at the edge, Skip check when is in scroll
  20. if (originScroll(false, deltaY)) return;
  21. // Skip if nest List has handled this event
  22. var event = e;
  23. if (!event._virtualHandled) {
  24. event._virtualHandled = true;
  25. } else {
  26. return;
  27. }
  28. offsetRef.current += deltaY;
  29. wheelValueRef.current = deltaY;
  30. // Proxy of scroll events
  31. if (!isFF) {
  32. event.preventDefault();
  33. }
  34. nextFrameRef.current = raf(function () {
  35. // Patch a multiple for Firefox to fix wheel number too small
  36. // ref: https://github.com/ant-design/ant-design/issues/26372#issuecomment-679460266
  37. var patchMultiple = isMouseScrollRef.current ? 10 : 1;
  38. onWheelDelta(offsetRef.current * patchMultiple, false);
  39. offsetRef.current = 0;
  40. });
  41. }
  42. function onWheelX(event, deltaX) {
  43. onWheelDelta(deltaX, true);
  44. if (!isFF) {
  45. event.preventDefault();
  46. }
  47. }
  48. // Check for which direction does wheel do. `sx` means `shift + wheel`
  49. var wheelDirectionRef = useRef(null);
  50. var wheelDirectionCleanRef = useRef(null);
  51. function onWheel(event) {
  52. if (!inVirtual) return;
  53. // Wait for 2 frame to clean direction
  54. raf.cancel(wheelDirectionCleanRef.current);
  55. wheelDirectionCleanRef.current = raf(function () {
  56. wheelDirectionRef.current = null;
  57. }, 2);
  58. var deltaX = event.deltaX,
  59. deltaY = event.deltaY,
  60. shiftKey = event.shiftKey;
  61. var mergedDeltaX = deltaX;
  62. var mergedDeltaY = deltaY;
  63. if (wheelDirectionRef.current === 'sx' || !wheelDirectionRef.current && (shiftKey || false) && deltaY && !deltaX) {
  64. mergedDeltaX = deltaY;
  65. mergedDeltaY = 0;
  66. wheelDirectionRef.current = 'sx';
  67. }
  68. var absX = Math.abs(mergedDeltaX);
  69. var absY = Math.abs(mergedDeltaY);
  70. if (wheelDirectionRef.current === null) {
  71. wheelDirectionRef.current = horizontalScroll && absX > absY ? 'x' : 'y';
  72. }
  73. if (wheelDirectionRef.current === 'y') {
  74. onWheelY(event, mergedDeltaY);
  75. } else {
  76. onWheelX(event, mergedDeltaX);
  77. }
  78. }
  79. // A patch for firefox
  80. function onFireFoxScroll(event) {
  81. if (!inVirtual) return;
  82. isMouseScrollRef.current = event.detail === wheelValueRef.current;
  83. }
  84. return [onWheel, onFireFoxScroll];
  85. }