Skip to content

Commit

Permalink
use scrollcoordinates to determine scroll positions
Browse files Browse the repository at this point in the history
  • Loading branch information
KingSora committed May 7, 2024
1 parent d2afdad commit 955b72c
Show file tree
Hide file tree
Showing 13 changed files with 420 additions and 294 deletions.
3 changes: 1 addition & 2 deletions packages/overlayscrollbars/src/classnames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ export const dataAttributeHost = dataAttributePrefix;
export const dataAttributeViewport = `${dataAttributePrefix}-viewport`;
export const dataValueViewportOverflowXPrefix = strOverflowX;
export const dataValueViewportOverflowYPrefix = strOverflowY;
export const dataValueViewportOverflowVisible = 'overflowVisible';
export const dataValueViewportOverflowHidden = 'overflowHidden';
export const dataValueViewportArrange = 'arrange';
export const dataValueViewportMeasuring = 'measuring';
export const dataValueViewportScrollbarHidden = 'scrollbarHidden';
export const dataValueViewportScrollbarPressed = 'scrollbarPressed';
export const dataValueViewportNoContent = 'noContent';

// padding
export const dataAttributePadding = `${dataAttributePrefix}-padding`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
addClass,
appendChildren,
createDiv,
getDirectionIsRTL,
each,
getTrasformTranslateValue,
isBoolean,
Expand All @@ -23,10 +22,10 @@ import {
numberToCssPx,
setStyles,
createOrKeepArray,
getRawScrollBounds,
getRawScrollRatio,
getBoundingClientRect,
capNumber,
getScrollPercent,
isDefaultScrollCoordinates,
} from '~/support';
import {
classNameScrollbar,
Expand All @@ -37,7 +36,6 @@ import {
} from '~/classnames';
import { getEnvironment } from '~/environment';
import { dynamicInitializationElement as generalDynamicInitializationElement } from '~/initialization';
import type { RTLScrollBehavior } from '~/support';
import type {
InitializationTarget,
InitializationTargetElement,
Expand Down Expand Up @@ -91,7 +89,7 @@ export const createScrollbarsSetupElements = (
structureSetupState: StructureSetupState,
scrollbarsSetupEvents: ScrollbarsSetupEvents
): ScrollbarsSetupElements => {
const { _getDefaultInitialization, _rtlScrollBehavior } = getEnvironment();
const { _getDefaultInitialization } = getEnvironment();
const { scrollbars: defaultInitScrollbars } = _getDefaultInitialization();
const { slot: defaultInitScrollbarsSlot } = defaultInitScrollbars;
const {
Expand Down Expand Up @@ -130,7 +128,7 @@ export const createScrollbarsSetupElements = (
* @returns The scrollbar handle length ratio.
*/
const getScrollbarHandleLengthRatio = (
isHorizontal?: boolean,
isHorizontal: boolean | undefined,
scrollbarStructure?: ScrollbarStructure
) => {
if (scrollbarStructure) {
Expand Down Expand Up @@ -163,16 +161,11 @@ export const createScrollbarsSetupElements = (
const getScrollbarHandleOffsetRatio = (
scrollbarStructure: ScrollbarStructure,
scrollPercent: number,
isHorizontal?: boolean,
rtlScrollBehavior?: RTLScrollBehavior
isHorizontal?: boolean
) => {
const lengthRatio = getScrollbarHandleLengthRatio(isHorizontal, scrollbarStructure);

return (
(1 / lengthRatio) *
(1 - lengthRatio) *
(rtlScrollBehavior ? 1 - scrollPercent : scrollPercent) || 0
);
return (1 / lengthRatio) * (1 - lengthRatio) * scrollPercent;
};

/**
Expand All @@ -181,18 +174,11 @@ export const createScrollbarsSetupElements = (
* @param directionRTL Whether the direction is RTL.
* @returns The passed keyframes with additional directional keyframes.
*/
const addDirectionRTLKeyframes = (
keyframes: Keyframe[] | PropertyIndexedKeyframes | null,
directionRTL?: boolean | RTLScrollBehavior
) =>
assignDeep(
keyframes,
directionRTL
? {
clear: ['left'], // dummy keyframe for direction rtl animation because of chrome bug
}
: {}
);
const addDirectionRTLKeyframes = (keyframes: Keyframe[] | PropertyIndexedKeyframes | null) =>
assignDeep(keyframes, {
// dummy keyframe which fixes bug where the scrollbar handle is reverted to origin position when it should be at its max position
clear: ['left'],
});

/**
* Cancels the animations of the passed elements or of all elements if no elements are passed.
Expand Down Expand Up @@ -257,7 +243,7 @@ export const createScrollbarsSetupElements = (
scrollbarStructures: ScrollbarStructure[],
elmStyle: (
scrollbarStructure: ScrollbarStructure
) => [HTMLElement | false | null | undefined, StyleObject]
) => [HTMLElement | false | null | undefined, StyleObject | false | null | undefined]
) => {
each(scrollbarStructures, (scrollbarStructure) => {
const [elm, styles] = elmStyle(scrollbarStructure);
Expand All @@ -284,58 +270,42 @@ export const createScrollbarsSetupElements = (
scrollbarStructures: ScrollbarStructure[],
isHorizontal?: boolean
) => {
const { _overflowAmount } = structureSetupState;
const overflowAmount = isHorizontal ? _overflowAmount.x : _overflowAmount.y;
const getTransformValue = (
structure: ScrollbarStructure,
rawScrollPosition: number,
rtlScrollBehavior: RTLScrollBehavior
) =>
const { _scrollCoordinates } = structureSetupState;
const xyKey = isHorizontal ? 'x' : 'y';
const scrollCoordsDefault = isDefaultScrollCoordinates(_scrollCoordinates)[xyKey];
const getTransformValue = (scrollbarStructure: ScrollbarStructure, scrollPercent: number) =>
getTrasformTranslateValue(
ratioToCssPercent(
getScrollbarHandleOffsetRatio(
structure,
getRawScrollRatio(rawScrollPosition, overflowAmount, rtlScrollBehavior),
isHorizontal,
rtlScrollBehavior
scrollbarStructure,
scrollCoordsDefault ? scrollPercent : 1 - scrollPercent,
isHorizontal
)
),
isHorizontal
);

if (scrollTimelineX && scrollTimelineY) {
each(scrollbarStructures, (structure: ScrollbarStructure) => {
const { _scrollbar, _handle } = structure;
const rtlScrollBehavior =
isHorizontal && getDirectionIsRTL(_scrollbar) && _rtlScrollBehavior;

const { _handle } = structure;
setElementAnimation(
_handle,
isHorizontal ? scrollTimelineX : scrollTimelineY,
addDirectionRTLKeyframes(
{
transform: getRawScrollBounds(overflowAmount, rtlScrollBehavior).map((bound) =>
getTransformValue(structure, bound, rtlScrollBehavior)
),
},
rtlScrollBehavior
)
addDirectionRTLKeyframes({
transform: [0, 1].map((percent) => getTransformValue(structure, percent)),
})
);
});
} else {
const scroll = getElementScroll(_scrollOffsetElement);
scrollbarStyle(scrollbarStructures, (structure) => {
const { _handle, _scrollbar } = structure;
return [
_handle,
{
transform: getTransformValue(
structure,
isHorizontal ? scroll.x : scroll.y,
isHorizontal && getDirectionIsRTL(_scrollbar) && _rtlScrollBehavior
),
},
];
});
scrollbarStyle(scrollbarStructures, (structure) => [
structure._handle,
{
transform: getTransformValue(
structure,
getScrollPercent(_scrollCoordinates, getElementScroll(_scrollOffsetElement))[xyKey]
),
},
]);
}
};
const doRefreshScrollbarOffset = (scrollbar: HTMLElement) =>
Expand Down Expand Up @@ -366,69 +336,73 @@ export const createScrollbarsSetupElements = (
};
const refreshScrollbarsScrollbarOffset = () => {
if (_viewportIsTarget) {
const { _overflowAmount } = structureSetupState;
const { _overflowAmount, _scrollCoordinates } = structureSetupState;
const isDefaultCoordinates = isDefaultScrollCoordinates(_scrollCoordinates);
const cushion = 0.5; // otherwise it sometimes happens that scrolling to 100% will cause the scrollbars to disappear
if (scrollTimelineX && scrollTimelineY) {
each(concat(verticalScrollbars, horizontalScrollbars), ({ _scrollbar }) => {
if (doRefreshScrollbarOffset(_scrollbar)) {
const setScrollbarElementAnimation = (
timeline: AnimationTimeline,
overflowAmount: number,
axisTimeline: AnimationTimeline,
axisOverflowAmount: number,
axisIsDefaultCoordinates: boolean,
isHorizontal?: boolean
) => {
const rtlScrollBehavior =
isHorizontal && getDirectionIsRTL(_scrollbar) && _rtlScrollBehavior;
) =>
setElementAnimation(
_scrollbar,
timeline,
addDirectionRTLKeyframes(
{
transform: getRawScrollBounds(overflowAmount - cushion, rtlScrollBehavior).map(
(bound) => getTrasformTranslateValue(numberToCssPx(bound), isHorizontal)
),
},
rtlScrollBehavior
),
axisTimeline,
addDirectionRTLKeyframes({
transform: [0, axisIsDefaultCoordinates ? 1 : -1].map((percent) =>
getTrasformTranslateValue(
numberToCssPx(percent * (axisOverflowAmount - cushion)),
isHorizontal
)
),
}),
'add'
);
};

setScrollbarElementAnimation(scrollTimelineX, _overflowAmount.x, true);
setScrollbarElementAnimation(scrollTimelineY, _overflowAmount.y);
setScrollbarElementAnimation(
scrollTimelineX,
_overflowAmount.x,
isDefaultCoordinates.x,
true
);
setScrollbarElementAnimation(
scrollTimelineY,
_overflowAmount.y,
isDefaultCoordinates.y
);
} else {
cancelElementAnimations(_scrollbar);
}
});
} else {
const scroll = getElementScroll(_scrollOffsetElement);
const scrollPercent = getScrollPercent(
_scrollCoordinates,
getElementScroll(_scrollOffsetElement)
);
const styleScrollbarPosition = (structure: ScrollbarStructure) => {
const { _scrollbar } = structure;
const elm = doRefreshScrollbarOffset(_scrollbar) && _scrollbar;
const getTranslateValue = (
axisScroll: number,
axisScrollPercent: number,
axisOverflowAmount: number,
rtlScrollBehavior?: RTLScrollBehavior
axisIsDefaultCoordinates: boolean
) => {
const percent = getRawScrollRatio(axisScroll, axisOverflowAmount, rtlScrollBehavior);
const px = axisOverflowAmount * percent;
return numberToCssPx(rtlScrollBehavior ? -px : px);
const px = axisOverflowAmount * axisScrollPercent;
return numberToCssPx(axisIsDefaultCoordinates ? px : -px);
};

return [
elm,
{
transform: elm
? getTrasformTranslateValue({
x: getTranslateValue(
scroll.x,
_overflowAmount.x,
getDirectionIsRTL(_scrollbar) && _rtlScrollBehavior
),
y: getTranslateValue(scroll.y, _overflowAmount.y),
})
: '',
elm && {
transform: getTrasformTranslateValue({
x: getTranslateValue(scrollPercent.x, _overflowAmount.x, isDefaultCoordinates.x),
y: getTranslateValue(scrollPercent.y, _overflowAmount.y, isDefaultCoordinates.y),
}),
},
] as [HTMLElement | false, StyleObject];
] as [HTMLElement | false, StyleObject | false];
};
scrollbarStyle(horizontalScrollbars, styleScrollbarPosition);
scrollbarStyle(verticalScrollbars, styleScrollbarPosition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export const createScrollbarsSetupEvents = (
mathRound(getBoundingClientRect(_scrollOffsetElement)[widthHeightKey]) /
getOffsetSize(_scrollOffsetElement)[whKey] || 1;
const moveHandleRelative = createRelativeHandleMove(
getElementScroll(_scrollOffsetElement)[xyKey] || 0,
getElementScroll(_scrollOffsetElement)[xyKey],
1 / axisScale
);
const pointerDownOffset = pointerDownEvent[clientXYKey];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,12 @@ export const createScrollbarsSetup = (
return [
() => bind(runEachAndClear, push(destroyFns, appendElements())),
({ _checkOption, _force, _observersUpdateHints, _structureUpdateHints }) => {
const { _overflowEdgeChanged, _overflowAmountChanged, _overflowStyleChanged } =
_structureUpdateHints || {};
const {
_overflowEdgeChanged,
_overflowAmountChanged,
_overflowStyleChanged,
_scrollCoordinatesChanged,
} = _structureUpdateHints || {};
const { _directionChanged, _appear } = _observersUpdateHints || {};
const { _directionIsRTL } = observersSetupState;
const { _nativeScrollbarsOverlaid } = getEnvironment();
Expand All @@ -180,7 +184,11 @@ export const createScrollbarsSetup = (
const trulyAppeared = _appear && !_force;
const hasOverflow = _hasOverflow.x || _hasOverflow.y;
const updateScrollbars =
_overflowEdgeChanged || _overflowAmountChanged || _directionChanged || _force;
_overflowEdgeChanged ||
_overflowAmountChanged ||
_scrollCoordinatesChanged ||
_directionChanged ||
_force;
const updateVisibility = _overflowStyleChanged || visibilityChanged || overflowChanged;
const showNativeOverlaidScrollbars =
showNativeOverlaidScrollbarsOption &&
Expand Down

0 comments on commit 955b72c

Please sign in to comment.