react-scroll-motion
Version:
Easy to make scroll animation with ReactJS
102 lines (101 loc) • 5.41 kB
JavaScript
"use client";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importStar(require("react"));
var constants_1 = require("./constants");
var stores_1 = require("./stores");
var utils_1 = require("./utils");
var _window = typeof window !== "undefined" ? window : undefined;
var ScrollContainer = function (props) {
var _a = props.snap, snap = _a === void 0 ? "none" : _a, children = props.children, _scrollParent = props.scrollParent, style = props.style, className = props.className;
var scrollParent = _scrollParent || _window;
var _b = (0, react_1.useState)(constants_1.initialScrollData), scrollData = _b[0], setScrollData = _b[1];
var containerRef = (0, react_1.useRef)(null);
var scrollTimer = (0, react_1.useRef)(null);
var scrollEvent = (0, react_1.useCallback)(function () {
if (snap !== "none" && scrollTimer.current)
clearTimeout(scrollTimer.current);
var container = containerRef.current;
if (!container)
return;
var currentScrollTop = scrollParent === window
? window.pageYOffset
: scrollParent.scrollTop;
var offsetTop = container.getBoundingClientRect().top + currentScrollTop;
var currentY = currentScrollTop - offsetTop;
var viewportHeight = scrollParent === window
? utils_1.environment.height
: scrollParent.clientHeight;
var totalPage = Array.isArray(children) ? children === null || children === void 0 ? void 0 : children.length : 1;
var totalHeight = totalPage * (viewportHeight - 1);
var totalProgress = currentY / totalHeight; // total page progress 0 ~ 1
var realPage = currentY / viewportHeight; // decimal page number
var currentPage = Math.floor(realPage); // integer page number
var currentProgress = realPage - currentPage; // current page progress
setScrollData(function (scrollData) {
return (__assign(__assign({}, scrollData), { currentY: currentY, viewportHeight: viewportHeight, totalPage: totalPage, totalHeight: totalHeight, totalProgress: totalProgress, realPage: realPage, currentPage: currentPage, currentProgress: currentProgress }));
});
if (snap !== "none") {
scrollTimer.current = setTimeout(function () {
var newCurrentPage = Math.round(realPage);
var newCurrentY = currentY;
if (snap === "mandatory" || Math.abs(newCurrentPage - realPage) < 0.3)
newCurrentY = newCurrentPage * viewportHeight;
if (newCurrentY !== currentY)
window.scrollTo({
top: newCurrentY + offsetTop,
behavior: "smooth",
});
}, 50);
}
}, [children, scrollParent, snap, setScrollData]);
(0, react_1.useEffect)(function () {
if (scrollParent) {
scrollEvent();
scrollParent.addEventListener("scroll", scrollEvent);
scrollParent.addEventListener("resize", scrollEvent);
return function () {
scrollParent.removeEventListener("scroll", scrollEvent);
scrollParent.removeEventListener("resize", scrollEvent);
};
}
}, [scrollEvent, scrollParent]);
return (react_1.default.createElement("div", { ref: containerRef, style: __assign({ margin: 0, padding: 0, userSelect: "none" }, style), className: className },
react_1.default.createElement(stores_1.ScrollDataContext.Provider, { value: scrollData }, (Array.isArray(children) &&
children.map(function (child, index) { return (react_1.default.createElement(stores_1.ScrollPageContext.Provider, { value: { page: index }, key: "scroll-page-".concat(index) }, child)); })) || (react_1.default.createElement(stores_1.ScrollPageContext.Provider, { value: { page: 0 } }, children)))));
};
exports.default = ScrollContainer;
;