mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-19 18:10:35 +03:00
scrollbar handle offset update
This commit is contained in:
+4
-4
@@ -85,15 +85,15 @@
|
|||||||
|
|
||||||
@-webkit-keyframes os-size-observer-appear-animation {
|
@-webkit-keyframes os-size-observer-appear-animation {
|
||||||
from {
|
from {
|
||||||
z-index: 0; }
|
cursor: auto; }
|
||||||
to {
|
to {
|
||||||
z-index: -1; } }
|
cursor: none; } }
|
||||||
|
|
||||||
@keyframes os-size-observer-appear-animation {
|
@keyframes os-size-observer-appear-animation {
|
||||||
from {
|
from {
|
||||||
z-index: 0; }
|
cursor: auto; }
|
||||||
to {
|
to {
|
||||||
z-index: -1; } }
|
cursor: none; } }
|
||||||
|
|
||||||
.os-trinsic-observer {
|
.os-trinsic-observer {
|
||||||
flex: none;
|
flex: none;
|
||||||
|
|||||||
@@ -1832,15 +1832,16 @@ const createEventContentChange = (t, n, o) => {
|
|||||||
n();
|
n();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const i = on(o, c, (t => {
|
const listener = t => {
|
||||||
if (e) {
|
if (e) {
|
||||||
i();
|
off(o, c, listener);
|
||||||
s.delete(o);
|
s.delete(o);
|
||||||
} else {
|
} else {
|
||||||
n(t);
|
n(t);
|
||||||
}
|
}
|
||||||
}));
|
};
|
||||||
s.set(o, [ c, i ]);
|
on(o, c, listener);
|
||||||
|
s.set(o, [ c, () => off(o, c, listener) ]);
|
||||||
}))));
|
}))));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+7
-4
@@ -1877,15 +1877,18 @@
|
|||||||
u();
|
u();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var f = qr(e, i, (function(r) {
|
var f = function listener(r) {
|
||||||
if (t) {
|
if (t) {
|
||||||
f();
|
Fr(e, i, listener);
|
||||||
n.delete(e);
|
n.delete(e);
|
||||||
} else {
|
} else {
|
||||||
a(r);
|
a(r);
|
||||||
}
|
}
|
||||||
}));
|
};
|
||||||
n.set(e, [ i, f ]);
|
qr(e, i, f);
|
||||||
|
n.set(e, [ i, function() {
|
||||||
|
return Fr(e, i, f);
|
||||||
|
} ]);
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -18,7 +18,7 @@ import type {
|
|||||||
} from 'options';
|
} from 'options';
|
||||||
import type { Setup, StructureSetupState, StructureSetupStaticState } from 'setups';
|
import type { Setup, StructureSetupState, StructureSetupStaticState } from 'setups';
|
||||||
import type { InitializationTarget } from 'initialization';
|
import type { InitializationTarget } from 'initialization';
|
||||||
import type { OverflowStyle, StyleObject } from 'typings';
|
import type { OverflowStyle } from 'typings';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
export interface ScrollbarsSetupState {}
|
export interface ScrollbarsSetupState {}
|
||||||
@@ -43,8 +43,7 @@ const createSelfCancelTimeout = (timeout?: number | (() => number)) => {
|
|||||||
] as [timeout: (callback: () => any) => void, clear: () => void];
|
] as [timeout: (callback: () => any) => void, clear: () => void];
|
||||||
};
|
};
|
||||||
|
|
||||||
const refreshScrollbarHandleLength = (
|
const getScrollbarHandleRatio = (
|
||||||
setStyleFn: ScrollbarsSetupElement['_handleStyle'],
|
|
||||||
structureSetupState: StructureSetupState,
|
structureSetupState: StructureSetupState,
|
||||||
isHorizontal?: boolean
|
isHorizontal?: boolean
|
||||||
) => {
|
) => {
|
||||||
@@ -52,96 +51,53 @@ const refreshScrollbarHandleLength = (
|
|||||||
const axis = isHorizontal ? 'x' : 'y';
|
const axis = isHorizontal ? 'x' : 'y';
|
||||||
const viewportSize = _overflowEdge[axis];
|
const viewportSize = _overflowEdge[axis];
|
||||||
const overflowAmount = _overflowAmount[axis];
|
const overflowAmount = _overflowAmount[axis];
|
||||||
const handleRatio = min(1, viewportSize / (viewportSize + overflowAmount));
|
return min(1, viewportSize / (viewportSize + overflowAmount));
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshScrollbarHandleLength = (
|
||||||
|
setStyleFn: ScrollbarsSetupElement['_handleStyle'],
|
||||||
|
structureSetupState: StructureSetupState,
|
||||||
|
isHorizontal?: boolean
|
||||||
|
) =>
|
||||||
|
setStyleFn((structure) => [
|
||||||
|
structure._handle,
|
||||||
|
{
|
||||||
|
[isHorizontal ? 'width' : 'height']: `${(
|
||||||
|
getScrollbarHandleRatio(structureSetupState, isHorizontal) * 100
|
||||||
|
).toFixed(3)}%`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const refreshScrollbarHandlePosition = (
|
||||||
|
setStyleFn: ScrollbarsSetupElement['_handleStyle'],
|
||||||
|
structureSetupState: StructureSetupState,
|
||||||
|
viewport: HTMLElement,
|
||||||
|
isHorizontal?: boolean
|
||||||
|
) => {
|
||||||
|
const axis = isHorizontal ? 'x' : 'y';
|
||||||
|
const translateAxis = isHorizontal ? 'X' : 'Y';
|
||||||
|
const scrollLeftTop = isHorizontal ? 'Left' : 'Top';
|
||||||
|
const handleRatio = getScrollbarHandleRatio(structureSetupState, isHorizontal);
|
||||||
|
const scrollPosition = viewport[`scroll${scrollLeftTop}`] as number;
|
||||||
|
const scrollPositionMax =
|
||||||
|
(viewport[`scroll${scrollLeftTop}Max`] as number) ||
|
||||||
|
Math.floor(structureSetupState._overflowAmount[axis]);
|
||||||
|
|
||||||
setStyleFn((structure) => [
|
setStyleFn((structure) => [
|
||||||
structure._handle,
|
structure._handle,
|
||||||
{
|
{
|
||||||
[isHorizontal ? 'width' : 'height']: `${(handleRatio * 100).toFixed(3)}%`,
|
transform: scrollPositionMax
|
||||||
|
? `translate${translateAxis}(${(
|
||||||
|
(1 / handleRatio) *
|
||||||
|
(1 - handleRatio) *
|
||||||
|
(scrollPosition / scrollPositionMax) *
|
||||||
|
100
|
||||||
|
).toFixed(3)}%)`
|
||||||
|
: '',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const refreshScrollbarHandlePosition = (
|
|
||||||
setStyleFn: (styles: StyleObject) => void,
|
|
||||||
structureSetupState: StructureSetupState,
|
|
||||||
isHorizontal?: boolean
|
|
||||||
) => {
|
|
||||||
/*
|
|
||||||
//measure the handle length to respect min & max length
|
|
||||||
var handleLength = scrollbarVarsInfo._handleLength;
|
|
||||||
var trackLength = scrollbarVars._track[0]['offset' + scrollbarVars._Width_Height];
|
|
||||||
var handleTrackDiff = trackLength - handleLength;
|
|
||||||
var handleCSS = {};
|
|
||||||
var transformOffset;
|
|
||||||
var translateValue;
|
|
||||||
|
|
||||||
//DONT use the variable '_contentScrollSizeCache[scrollbarVars._w_h]' instead of '_viewportElement[0]['scroll' + scrollbarVars._Width_Height]'
|
|
||||||
// because its a bit behind during the small delay when content size updates
|
|
||||||
//(delay = mutationObserverContentLag, if its 0 then this var could be used)
|
|
||||||
var maxScroll =
|
|
||||||
(_viewportElementNative[_strScroll + scrollbarVars._Width_Height] -
|
|
||||||
_viewportElementNative['client' + scrollbarVars._Width_Height]) *
|
|
||||||
(_rtlScrollBehavior.n && isRTLisHorizontal ? -1 : 1); //* -1 if rtl scroll max is negative
|
|
||||||
var getScrollRatio = function (base) {
|
|
||||||
return isNaN(base / maxScroll) ? 0 : MATH.max(0, MATH.min(1, base / maxScroll));
|
|
||||||
};
|
|
||||||
var getHandleOffset = function (scrollRatio) {
|
|
||||||
var offset = handleTrackDiff * scrollRatio;
|
|
||||||
offset = isNaN(offset) ? 0 : offset;
|
|
||||||
offset =
|
|
||||||
isRTLisHorizontal && !_rtlScrollBehavior.i ? trackLength - handleLength - offset : offset;
|
|
||||||
offset = MATH.max(0, offset);
|
|
||||||
return offset;
|
|
||||||
};
|
|
||||||
var scrollRatio = getScrollRatio(nativeScroll);
|
|
||||||
var unsnappedScrollRatio = getScrollRatio(currentScroll);
|
|
||||||
var handleOffset = getHandleOffset(unsnappedScrollRatio);
|
|
||||||
var snappedHandleOffset = getHandleOffset(scrollRatio);
|
|
||||||
|
|
||||||
scrollbarVarsInfo._maxScroll = maxScroll;
|
|
||||||
scrollbarVarsInfo._currentScroll = nativeScroll;
|
|
||||||
scrollbarVarsInfo._currentScrollRatio = scrollRatio;
|
|
||||||
|
|
||||||
if (_supportTransform) {
|
|
||||||
transformOffset = isRTLisHorizontal
|
|
||||||
? -(trackLength - handleLength - handleOffset)
|
|
||||||
: handleOffset; //in px
|
|
||||||
//transformOffset = (transformOffset / trackLength * 100) * (trackLength / handleLength); //in %
|
|
||||||
translateValue = isHorizontal
|
|
||||||
? strTranslateBrace + transformOffset + 'px, 0)'
|
|
||||||
: strTranslateBrace + '0, ' + transformOffset + 'px)';
|
|
||||||
|
|
||||||
handleCSS[strTransform] = translateValue;
|
|
||||||
|
|
||||||
//apply or clear up transition
|
|
||||||
if (_supportTransition)
|
|
||||||
handleCSS[strTransition] =
|
|
||||||
transition && MATH.abs(handleOffset - scrollbarVarsInfo._handleOffset) > 1
|
|
||||||
? getCSSTransitionString(scrollbarVars._handle) +
|
|
||||||
', ' +
|
|
||||||
(strTransform + _strSpace + transitionDuration + 'ms')
|
|
||||||
: _strEmpty;
|
|
||||||
} else handleCSS[scrollbarVars._left_top] = handleOffset;
|
|
||||||
|
|
||||||
//only apply css if offset has changed and overflow exists.
|
|
||||||
if (!nativeOverlayScrollbarsAreActive()) {
|
|
||||||
scrollbarVars._handle.css(handleCSS);
|
|
||||||
|
|
||||||
//clear up transition
|
|
||||||
if (_supportTransform && _supportTransition && transition) {
|
|
||||||
scrollbarVars._handle.one(_strTransitionEndEvent, function () {
|
|
||||||
if (!_destroyed) scrollbarVars._handle.css(strTransition, _strEmpty);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollbarVarsInfo._handleOffset = handleOffset;
|
|
||||||
scrollbarVarsInfo._snappedHandleOffset = snappedHandleOffset;
|
|
||||||
scrollbarVarsInfo._trackLength = trackLength;
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createScrollbarsSetup = (
|
export const createScrollbarsSetup = (
|
||||||
target: InitializationTarget,
|
target: InitializationTarget,
|
||||||
options: ReadonlyOSOptions,
|
options: ReadonlyOSOptions,
|
||||||
@@ -215,13 +171,16 @@ export const createScrollbarsSetup = (
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
on(_viewport, 'scroll', () => {
|
on(_viewport, 'scroll', () => {
|
||||||
autoHideNotNever &&
|
requestScrollAnimationFrame(() => {
|
||||||
requestScrollAnimationFrame(() => {
|
const structureState = structureSetupState();
|
||||||
manageScrollbarsAutoHide(true);
|
refreshScrollbarHandlePosition(styleHorizontal, structureState, _viewport, true);
|
||||||
scrollTimeout(() => {
|
refreshScrollbarHandlePosition(styleVertical, structureState, _viewport);
|
||||||
autoHideNotNever && !mouseInHost && manageScrollbarsAutoHide(false);
|
|
||||||
});
|
autoHideNotNever && manageScrollbarsAutoHide(true);
|
||||||
|
scrollTimeout(() => {
|
||||||
|
autoHideNotNever && !mouseInHost && manageScrollbarsAutoHide(false);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
const scrollbarsSetupState = getState.bind(0) as (() => ScrollbarsSetupState) &
|
const scrollbarsSetupState = getState.bind(0) as (() => ScrollbarsSetupState) &
|
||||||
@@ -289,6 +248,9 @@ export const createScrollbarsSetup = (
|
|||||||
if (updateHandle) {
|
if (updateHandle) {
|
||||||
refreshScrollbarHandleLength(styleHorizontal, currStructureSetupState, true);
|
refreshScrollbarHandleLength(styleHorizontal, currStructureSetupState, true);
|
||||||
refreshScrollbarHandleLength(styleVertical, currStructureSetupState);
|
refreshScrollbarHandleLength(styleVertical, currStructureSetupState);
|
||||||
|
|
||||||
|
refreshScrollbarHandlePosition(styleHorizontal, currStructureSetupState, _viewport, true);
|
||||||
|
refreshScrollbarHandlePosition(styleVertical, currStructureSetupState, _viewport);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollbarsSetupState,
|
scrollbarsSetupState,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
.os-scrollbar {
|
.os-scrollbar {
|
||||||
|
contain: strict;
|
||||||
transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
|
transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
Reference in New Issue
Block a user