Skip to content

Commit

Permalink
fix: mac 下长目录无法跟随滚动 & 优化滚动效果
Browse files Browse the repository at this point in the history
  • Loading branch information
Mereithhh committed Sep 7, 2022
1 parent 3589feb commit 9296820
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 55 deletions.
9 changes: 7 additions & 2 deletions packages/website/components/BackToTop/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import style from "../../styles/back-to-top.module.css";
import scroll from "react-scroll";
import { scrollTo } from "../../utils/scroll";
import { debounce } from "../../utils/debounce";
interface BackToTopBtnProps {}
function getScrollTop() {
Expand Down Expand Up @@ -38,7 +38,12 @@ const BackToTopBtn: React.FC<BackToTopBtnProps> = (props) => {
}, 500);

const backToTopHandle = () => {
scroll.animateScroll.scrollToTop();
scrollTo(window, {
top: 0,
// behavior: "smooth",
easing: "ease-in-out",
duration: 800,
});
};

return (
Expand Down
20 changes: 10 additions & 10 deletions packages/website/components/MarkdownTocBar/core.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useEffect, useState } from "react";
import throttle from "lodash/throttle";
import { NavItem } from "./tools";

import scroll from "react-scroll";
import { scrollTo } from "../../utils/scroll";
export default function (props: { items: NavItem[]; headingOffset: number }) {
const { items } = props;
const [currIndex, setCurrIndex] = useState(-1);
Expand Down Expand Up @@ -40,16 +39,17 @@ export default function (props: { items: NavItem[]; headingOffset: number }) {
}, 100);
useEffect(() => {
const el = document.querySelector(".markdown-navigation div.active");
if (el) {
const container = document.querySelector("#toc-container");
if (el && container) {
let to = (el as any)?.offsetTop;
if (to <= props.headingOffset) {
to = 0;
} else {
to = to - 100;
}
scroll.animateScroll.scrollTo(to, {
containerId: "toc-container",
smooth: true,
delay: 0,
spyThrottle: 0,
scrollTo(container, {
top: to,
behavior: "smooth",
});
}
}, [currIndex, props.headingOffset]);
Expand Down Expand Up @@ -77,7 +77,7 @@ export default function (props: { items: NavItem[]; headingOffset: number }) {
if (to <= 100) {
to = 0;
}
scroll.animateScroll.scrollTo(to);
scrollTo(window, { top: to, easing: "ease-in-out", duration: 800 });
}
}}
>
Expand All @@ -90,7 +90,7 @@ export default function (props: { items: NavItem[]; headingOffset: number }) {
<div
className="text-center text-lg font-medium mt-4 text-gray-700 dark:text-dark cursor-pointer"
onClick={() => {
scroll.animateScroll.scrollToTop();
scrollTo(window, { top: 0, easing: "ease-in-out", duration: 800 });
}}
>
目录
Expand Down
29 changes: 0 additions & 29 deletions packages/website/components/Toc/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,35 +34,6 @@ export default function (props: {
style={{ maxHeight: 450 }}
>
<MarkdownTocBar content={props.content} headingOffset={56} />
{/* <MarkdownNavbar
ordered={false}
declarative={true}
// updateHashAuto={true}
source={props.content.replace(/`#/g, "")}
headingTopOffset={56}
onHashChange={(newHash: string, oldHash: string) => {
// 判断一下当前激活的元素
const el = document.querySelector(
".markdown-navigation div.active"
);
let to = (el as any)?.offsetTop;
// console.log(to);
if (to) {
if (newHash < oldHash) {
to = to - 100;
}
scroll.animateScroll.scrollTo(to, {
containerId: "toc-container",
smooth: true,
delay: 0,
spyThrottle: 0,
});
}
// console.log(newHash, oldHash, el);
}}
/> */}
</div>
</div>
);
Expand Down
1 change: 0 additions & 1 deletion packages/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"react-hot-toast": "^2.3.0",
"react-markdown": "^8.0.3",
"react-photo-view": "^1.2.2",
"react-scroll": "^1.8.7",
"react-syntax-highlighter": "^15.5.0",
"react-tiny-popover": "^7.1.0",
"react-use": "^17.4.0",
Expand Down
214 changes: 214 additions & 0 deletions packages/website/utils/scroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
type EasingOptions = "linear" | "ease-in" | "ease-out" | "ease-in-out";

export interface ScrollToCustomOptions extends ScrollToOptions {
duration?: number;
easing?: EasingOptions;
}

export const DEFAULT_DURATION = 300;

export async function scrollTo(
el: Element | Window,
options: ScrollToCustomOptions = {}
) {
if (!(el instanceof Element) && !(el instanceof Window)) {
throw new Error(
`element passed to scrollTo() must be either the window or a DOM element, you passed ${el}!`
);
}

options = sanitizeScrollOptions(options);

const scroll = (
from: number,
to: number,
prop: string,
startTime: number,
duration: number | undefined = DEFAULT_DURATION,
easeFunc: EasingFunction,
callback: Function
) => {
window.requestAnimationFrame(() => {
const currentTime = Date.now();
const time = Math.min(1, (currentTime - startTime) / duration);

if (from === to) {
return callback ? callback() : null;
}

setScrollPosition(el, easeFunc(time) * (to - from) + from);

/* prevent scrolling, if already there, or at end */
if (time < 1) {
scroll(from, to, prop, startTime, duration, easeFunc, callback);
} else if (callback) {
callback();
}
});
};

const currentScrollPosition = getScrollPosition(el);
const scrollProperty = getScrollPropertyByElement(el);
return new Promise((resolve) => {
scroll(
currentScrollPosition,
typeof options.top === "number" ? options.top : currentScrollPosition,
scrollProperty,
Date.now(),
options.duration,
getEasing(options.easing),
resolve
);
});
}

export function scrollIntoView(
element: HTMLElement,
scroller?: Element | ScrollIntoViewOptions,
options?: ScrollIntoViewOptions
) {
validateElement(element);
if (scroller && !(scroller instanceof Element)) {
options = scroller;
scroller = undefined;
}
const { duration, easing } = sanitizeScrollOptions(options);
scroller = scroller || utils.getDocument().body;
let currentContainerScrollYPos = 0;
let elementScrollYPos = element ? element.offsetTop : 0;
const document = utils.getDocument();

// if the container is the document body or document itself, we'll
// need a different set of coordinates for accuracy
if (scroller === document.body || scroller === document.documentElement) {
// using pageYOffset for cross-browser compatibility
currentContainerScrollYPos = window.pageYOffset;
// must add containers scroll y position to ensure an absolute value that does not change
elementScrollYPos =
element.getBoundingClientRect().top + currentContainerScrollYPos;
}

return scrollTo(scroller as Element, {
top: elementScrollYPos,
left: 0,
duration,
easing,
});
}

function validateElement(element?: HTMLElement) {
if (element === undefined) {
const errorMsg = "The element passed to scrollIntoView() was undefined.";
throw new Error(errorMsg);
}
if (!(element instanceof HTMLElement)) {
throw new Error(
`The element passed to scrollIntoView() must be a valid element. You passed ${element}.`
);
}
}

function getScrollPropertyByElement(
el: Element | Window
): "scrollY" | "scrollX" | "scrollTop" | "scrollLeft" {
const props: any = {
window: {
y: "scrollY",
x: "scrollX",
},
element: {
y: "scrollTop",
x: "scrollLeft",
},
};
const axis = "y";
if (el instanceof Window) {
return props.window[axis];
} else {
return props.element[axis];
}
}

function sanitizeScrollOptions(
options: ScrollToCustomOptions = {}
): ScrollToCustomOptions {
if (options.behavior === "smooth") {
options.easing = "ease-in-out";
options.duration = DEFAULT_DURATION;
}
if (options.behavior === "auto") {
options.duration = 0;
options.easing = "linear";
}
return options;
}

function getScrollPosition(el: Element | Window): number {
const document = utils.getDocument();
if (
el === document.body ||
el === document.documentElement ||
el instanceof Window
) {
return document.body.scrollTop || document.documentElement.scrollTop;
} else {
return el.scrollTop;
}
}

function setScrollPosition(el: Element | Window, value: number) {
const document = utils.getDocument();
if (
el === document.body ||
el === document.documentElement ||
el instanceof Window
) {
document.body.scrollTop = value;
document.documentElement.scrollTop = value;
} else {
el.scrollTop = value;
}
}

export const utils = {
// we're really just exporting this so that tests can mock the document.documentElement
getDocument(): HTMLDocument {
return document;
},
};

// eslint-disable-next-line no-unused-vars
type EasingFunction = (t: number) => number;

interface EasingFunctions {
linear: EasingFunction;
"ease-in": EasingFunction;
"ease-out": EasingFunction;
"ease-in-out": EasingFunction;
}
export const easingMap: EasingFunctions = {
linear(t: number) {
return t;
},
"ease-in"(t: number) {
return t * t;
},
"ease-out"(t: number) {
return t * (2 - t);
},
"ease-in-out"(t: number) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
},
};

const getEasing = (easing?: EasingOptions): EasingFunction => {
const defaultEasing = "linear";
const easeFunc = easingMap[easing || defaultEasing];
if (!easeFunc) {
const options = Object.keys(easingMap).join(",");
throw new Error(
`Scroll error: scroller does not support an easing option of "${easing}". Supported options are ${options}`
);
}
return easeFunc;
};
13 changes: 0 additions & 13 deletions packages/website/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1834,11 +1834,6 @@ lilconfig@^2.0.5, lilconfig@^2.0.6:
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4"
integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==

lodash.throttle@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==

lodash@^4.17.15, lodash@^4.17.20:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
Expand Down Expand Up @@ -2736,14 +2731,6 @@ react-photo-view@^1.2.2:
resolved "https://registry.yarnpkg.com/react-photo-view/-/react-photo-view-1.2.2.tgz#deaed9af83ec5ccc1f240c58a62bffeb0a6c0187"
integrity sha512-/xsOiDuiR23hKxpmF73EDKPvsBvcWogolXvnBhMZV4CUhd9tnXF91amjKnuQe9BmLaR9CbNxXDOI9SNKeXT5ew==

react-scroll@^1.8.7:
version "1.8.7"
resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.8.7.tgz#8020035329efad00f03964e18aff6822137de3aa"
integrity sha512-fBOIwweAlhicx8RqP9tQXn/Uhd+DTtVRjw+0VBsIn1Z+MjRYLhTZ0tMoTAU1vOD3dce8mI6copexI4yWII+Luw==
dependencies:
lodash.throttle "^4.1.1"
prop-types "^15.7.2"

react-syntax-highlighter@^15.5.0:
version "15.5.0"
resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20"
Expand Down

0 comments on commit 9296820

Please sign in to comment.