81 lines
2.8 KiB
JavaScript
81 lines
2.8 KiB
JavaScript
import { scrollInfo } from './track.mjs';
|
|
import { observeTimeline } from './observe.mjs';
|
|
import { supportsScrollTimeline } from './supports.mjs';
|
|
|
|
function scrollTimelineFallback({ source, container, axis = "y", }) {
|
|
// Support legacy source argument. Deprecate later.
|
|
if (source)
|
|
container = source;
|
|
// ScrollTimeline records progress as a percentage CSSUnitValue
|
|
const currentTime = { value: 0 };
|
|
const cancel = scrollInfo((info) => {
|
|
currentTime.value = info[axis].progress * 100;
|
|
}, { container, axis });
|
|
return { currentTime, cancel };
|
|
}
|
|
const timelineCache = new Map();
|
|
function getTimeline({ source, container = document.documentElement, axis = "y", } = {}) {
|
|
// Support legacy source argument. Deprecate later.
|
|
if (source)
|
|
container = source;
|
|
if (!timelineCache.has(container)) {
|
|
timelineCache.set(container, {});
|
|
}
|
|
const elementCache = timelineCache.get(container);
|
|
if (!elementCache[axis]) {
|
|
elementCache[axis] = supportsScrollTimeline()
|
|
? new ScrollTimeline({ source: container, axis })
|
|
: scrollTimelineFallback({ source: container, axis });
|
|
}
|
|
return elementCache[axis];
|
|
}
|
|
/**
|
|
* If the onScroll function has two arguments, it's expecting
|
|
* more specific information about the scroll from scrollInfo.
|
|
*/
|
|
function isOnScrollWithInfo(onScroll) {
|
|
return onScroll.length === 2;
|
|
}
|
|
/**
|
|
* Currently, we only support element tracking with `scrollInfo`, though in
|
|
* the future we can also offer ViewTimeline support.
|
|
*/
|
|
function needsElementTracking(options) {
|
|
return options && (options.target || options.offset);
|
|
}
|
|
function scrollFunction(onScroll, options) {
|
|
if (isOnScrollWithInfo(onScroll) || needsElementTracking(options)) {
|
|
return scrollInfo((info) => {
|
|
onScroll(info[options.axis].progress, info);
|
|
}, options);
|
|
}
|
|
else {
|
|
return observeTimeline(onScroll, getTimeline(options));
|
|
}
|
|
}
|
|
function scrollAnimation(animation, options) {
|
|
if (needsElementTracking(options)) {
|
|
animation.pause();
|
|
return scrollInfo((info) => {
|
|
animation.time = animation.duration * info[options.axis].progress;
|
|
}, options);
|
|
}
|
|
else {
|
|
const timeline = getTimeline(options);
|
|
return animation.attachTimeline(timeline, (valueAnimation) => {
|
|
valueAnimation.pause();
|
|
return observeTimeline((progress) => {
|
|
valueAnimation.time = valueAnimation.duration * progress;
|
|
}, timeline);
|
|
});
|
|
}
|
|
}
|
|
function scroll(onScroll, { axis = "y", ...options } = {}) {
|
|
const optionsWithDefaults = { axis, ...options };
|
|
return typeof onScroll === "function"
|
|
? scrollFunction(onScroll, optionsWithDefaults)
|
|
: scrollAnimation(onScroll, optionsWithDefaults);
|
|
}
|
|
|
|
export { scroll };
|