{"size": 1346, "ext": "js", "max_stars_repo_path": "src/components/BackToTop/index.js", "max_stars_repo_name": "690243004/frontend_react_admin", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "src/components/BackToTop/index.js", "max_issues_repo_name": "690243004/frontend_react_admin", "max_issues_repo_issues_event_min_datetime": "2021-03-10T07:22:31.000Z", "max_issues_repo_issues_event_max_datetime": "2022-02-26T23:32:23.000Z", "max_forks_repo_path": "src/components/BackToTop/index.js", "max_forks_repo_name": "690243004/frontend_react_admin", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": 5, "max_forks_count": null, "avg_line_length": 23.6140350877, "max_line_length": 77, "alphanum_fraction": 0.603268945}
import React, { useEffect } from "react";
import "./index.less";

const OFFSET = 50; // 偏差值
const STEP_MAGNIFICATION = 5; // 移动速率

const BackToTop = () => {
  const hasScrollbar = dirction => {
    if (dirction === "vertical") {
      return element => element.scrollHeight - element.clientHeight > OFFSET;
    } else {
      return element => element.scrollWidth - element.clientWidth > OFFSET;
    }
  };

  // 广度优先搜索
  const bfs = root => callback => {
    const queue = [root];
    while (queue.length > 0) {
      const node = queue.shift();
      if (callback(node)) return node;
      if (node.childNodes) {
        queue.push(...node.childNodes);
      }
    }
  };

  let scrollContainer;

  useEffect(() => {
    scrollContainer = bfs(document.querySelector(".container"))(
      hasScrollbar("vertical")
    );
  }, []);

  const animate2Top = dom => {
    const scrollTop = dom.scrollTop;
    if (scrollTop > 0) {
      console.log(Math.floor(scrollTop / STEP_MAGNIFICATION));
      scrollContainer.scrollTo(0, Math.floor(scrollTop / 10));
      window.requestAnimationFrame(() => {
        animate2Top(dom);
      });
    }
  };

  const onBackToTop = () => {
    if (scrollContainer) {
      animate2Top(scrollContainer);
    }
  };

  return <div className="back-to-top" onClick={onBackToTop}></div>;
};

export default BackToTop;
