78 lines
2.7 KiB
JavaScript
78 lines
2.7 KiB
JavaScript
|
import { useRef } from 'react';
|
||
|
import raf from "rc-util/es/raf";
|
||
|
import isFF from '../utils/isFirefox';
|
||
|
import useOriginScroll from './useOriginScroll';
|
||
|
export default function useFrameWheel(inVirtual, isScrollAtTop, isScrollAtBottom, horizontalScroll,
|
||
|
/***
|
||
|
* Return `true` when you need to prevent default event
|
||
|
*/
|
||
|
onWheelDelta) {
|
||
|
var offsetRef = useRef(0);
|
||
|
var nextFrameRef = useRef(null);
|
||
|
// Firefox patch
|
||
|
var wheelValueRef = useRef(null);
|
||
|
var isMouseScrollRef = useRef(false);
|
||
|
// Scroll status sync
|
||
|
var originScroll = useOriginScroll(isScrollAtTop, isScrollAtBottom);
|
||
|
function onWheelY(event, deltaY) {
|
||
|
raf.cancel(nextFrameRef.current);
|
||
|
offsetRef.current += deltaY;
|
||
|
wheelValueRef.current = deltaY;
|
||
|
// Do nothing when scroll at the edge, Skip check when is in scroll
|
||
|
if (originScroll(deltaY)) return;
|
||
|
// Proxy of scroll events
|
||
|
if (!isFF) {
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
nextFrameRef.current = raf(function () {
|
||
|
// Patch a multiple for Firefox to fix wheel number too small
|
||
|
// ref: https://github.com/ant-design/ant-design/issues/26372#issuecomment-679460266
|
||
|
var patchMultiple = isMouseScrollRef.current ? 10 : 1;
|
||
|
onWheelDelta(offsetRef.current * patchMultiple);
|
||
|
offsetRef.current = 0;
|
||
|
});
|
||
|
}
|
||
|
function onWheelX(event, deltaX) {
|
||
|
onWheelDelta(deltaX, true);
|
||
|
if (!isFF) {
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
}
|
||
|
// Check for which direction does wheel do. `sx` means `shift + wheel`
|
||
|
var wheelDirectionRef = useRef(null);
|
||
|
var wheelDirectionCleanRef = useRef(null);
|
||
|
function onWheel(event) {
|
||
|
if (!inVirtual) return;
|
||
|
// Wait for 2 frame to clean direction
|
||
|
raf.cancel(wheelDirectionCleanRef.current);
|
||
|
wheelDirectionCleanRef.current = raf(function () {
|
||
|
wheelDirectionRef.current = null;
|
||
|
}, 2);
|
||
|
var deltaX = event.deltaX,
|
||
|
deltaY = event.deltaY,
|
||
|
shiftKey = event.shiftKey;
|
||
|
var mergedDeltaX = deltaX;
|
||
|
var mergedDeltaY = deltaY;
|
||
|
if (wheelDirectionRef.current === 'sx' || !wheelDirectionRef.current && (shiftKey || false) && deltaY && !deltaX) {
|
||
|
mergedDeltaX = deltaY;
|
||
|
mergedDeltaY = 0;
|
||
|
wheelDirectionRef.current = 'sx';
|
||
|
}
|
||
|
var absX = Math.abs(mergedDeltaX);
|
||
|
var absY = Math.abs(mergedDeltaY);
|
||
|
if (wheelDirectionRef.current === null) {
|
||
|
wheelDirectionRef.current = horizontalScroll && absX > absY ? 'x' : 'y';
|
||
|
}
|
||
|
if (wheelDirectionRef.current === 'y') {
|
||
|
onWheelY(event, mergedDeltaY);
|
||
|
} else {
|
||
|
onWheelX(event, mergedDeltaX);
|
||
|
}
|
||
|
}
|
||
|
// A patch for firefox
|
||
|
function onFireFoxScroll(event) {
|
||
|
if (!inVirtual) return;
|
||
|
isMouseScrollRef.current = event.detail === wheelValueRef.current;
|
||
|
}
|
||
|
return [onWheel, onFireFoxScroll];
|
||
|
}
|