UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

94 lines (93 loc) 3.43 kB
import React__default, { useState, useRef, useEffect } from "react"; import { Top } from "@nutui/icons-react"; import classNames from "classnames"; import { C as ComponentDefaults } from "./typings.js"; import { r as requestAniFrame } from "./raf.js"; import { useRtl } from "./ConfigProvider.js"; const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { target: "", threshold: 200, zIndex: 900, duration: 1e3 }); const BackTop = (props) => { const rtl = useRtl(); const { children, target, threshold, zIndex, className, duration, style, onClick } = Object.assign(Object.assign({}, defaultProps), props); const classPrefix = "nut-backtop"; const [backTop, SetBackTop] = useState(false); const [scrollTop, SetScrollTop] = useState(0); let startTime = 0; const scrollEl = useRef(null); useEffect(() => { init(); return () => removeEventListener(); }, []); const init = () => { if (target && document.getElementById(target)) { scrollEl.current = document.getElementById(target); } else { scrollEl.current = window; } addEventListener(); initCancelAniFrame(); }; const scrollListener = () => { let top = null; if (scrollEl.current instanceof Window) { top = scrollEl.current.pageYOffset; SetScrollTop(top); } else { top = scrollEl.current.scrollTop; SetScrollTop(top); } const showBtn = top >= threshold; SetBackTop(showBtn); }; const scroll = (y = 0) => { if (scrollEl.current instanceof Window) { window.scrollTo(0, y); } else { scrollEl.current.scrollTop = y; window.scrollTo(0, y); } }; const scrollAnimation = () => { let cid = requestAniFrame(function fn() { const t = duration - Math.max(0, startTime - +/* @__PURE__ */ new Date() + duration / 2); const y = t * -scrollTop / duration + scrollTop; scroll(y); cid = requestAniFrame(fn); if (t === duration || y === 0) { window.cancelAnimationFrame(cid); } }); }; const initCancelAniFrame = () => { window.cancelAnimationFrame = window.webkitCancelAnimationFrame; }; function addEventListener() { var _a, _b; (_a = scrollEl.current) === null || _a === void 0 ? void 0 : _a.addEventListener("scroll", scrollListener, false); (_b = scrollEl.current) === null || _b === void 0 ? void 0 : _b.addEventListener("resize", scrollListener, false); } function removeEventListener() { var _a, _b; (_a = scrollEl.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("scroll", scrollListener, false); (_b = scrollEl.current) === null || _b === void 0 ? void 0 : _b.removeEventListener("resize", scrollListener, false); } const goTop = (e) => { onClick && onClick(e); const otime = +/* @__PURE__ */ new Date(); startTime = otime; duration > 0 ? scrollAnimation() : scroll(); }; const styles = Object.keys(style || {}).length !== 0 ? Object.assign({ zIndex }, style) : { [rtl ? "left" : "right"]: "10px", bottom: "20px", zIndex }; return React__default.createElement("div", { className: classNames(classPrefix, { show: backTop }, className), style: styles, onClick: (e) => { goTop(e); } }, children || React__default.createElement(Top, { width: 19, height: 19, className: "nut-backtop-main" })); }; BackTop.displayName = "NutBackTop"; export { BackTop as default };