diff --git a/pages/[...slug].js b/pages/[...slug].js index b7c41a6d..d891ce06 100644 --- a/pages/[...slug].js +++ b/pages/[...slug].js @@ -49,7 +49,7 @@ const Slug = props => { }) } } - }, 20 * 1000) + }, 8 * 1000) // 404时长 const meta = { title: `${props?.siteInfo?.title || BLOG.TITLE} | loading`, image: siteInfo?.pageCover || BLOG.HOME_BANNER_IMAGE } return } diff --git a/themes/fukasawa/components/BlogListScroll.js b/themes/fukasawa/components/BlogListScroll.js index 003f789d..b6ec891c 100644 --- a/themes/fukasawa/components/BlogListScroll.js +++ b/themes/fukasawa/components/BlogListScroll.js @@ -3,7 +3,7 @@ import React from 'react' import BlogCard from './BlogCard' import BlogPostListEmpty from './BlogListEmpty' import { useGlobal } from '@/lib/global' -import throttle from 'lodash.throttle' + /** * 文章列表分页表格 * @param page 当前页 @@ -45,13 +45,15 @@ const BlogListScroll = props => { } // 监听滚动自动分页加载 - const scrollTrigger = React.useCallback(throttle(() => { - const scrollS = window.scrollY + window.outerHeight - const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 - if (scrollS > clientHeight + 100) { - handleGetMore() - } - }, 500)) + const scrollTrigger = () => { + requestAnimationFrame(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }) + } React.useEffect(() => { updateCol() @@ -68,22 +70,22 @@ const BlogListScroll = props => { return } else { return ( -
- {/* 文章列表 */} -
- {postsToShow?.map(post => ( -
- -
- ))} -
+
+ {/* 文章列表 */} +
+ {postsToShow?.map(post => ( +
+ +
+ ))} +
-
- {' '} - {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '} -
-
+
+ {' '} + {hasMore ? locale.COMMON.MORE : `${locale.COMMON.NO_MORE} 😰`}{' '} +
+
) } } diff --git a/themes/hexo/LayoutBase.js b/themes/hexo/LayoutBase.js index 4808648f..15c3a2e0 100644 --- a/themes/hexo/LayoutBase.js +++ b/themes/hexo/LayoutBase.js @@ -38,18 +38,20 @@ const LayoutBase = props => { const { onLoading } = useGlobal() const scrollListener = () => { - const targetRef = document.getElementById('wrapper') - const clientHeight = targetRef?.clientHeight - const scrollY = window.pageYOffset - const fullHeight = clientHeight - window.outerHeight - let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0)) - if (per > 100) per = 100 - const shouldShow = scrollY > 100 && per > 0 + requestAnimationFrame(() => { + const targetRef = document.getElementById('wrapper') + const clientHeight = targetRef?.clientHeight + const scrollY = window.pageYOffset + const fullHeight = clientHeight - window.outerHeight + let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0)) + if (per > 100) per = 100 + const shouldShow = scrollY > 100 && per > 0 - if (shouldShow !== show) { - switchShow(shouldShow) - } + if (shouldShow !== show) { + switchShow(shouldShow) + } // changePercent(per) + }) } useEffect(() => { document.addEventListener('scroll', scrollListener) @@ -78,12 +80,7 @@ const LayoutBase = props => { {/* 右下角悬浮 */}
-
+
{floatSlot} diff --git a/themes/hexo/LayoutIndex.js b/themes/hexo/LayoutIndex.js index 1361c1e6..be20b425 100644 --- a/themes/hexo/LayoutIndex.js +++ b/themes/hexo/LayoutIndex.js @@ -7,7 +7,8 @@ import LayoutBase from './LayoutBase' import React from 'react' export const LayoutIndex = (props) => { - return }> + const headerSlot = CONFIG_HEXO.HOME_BANNER_ENABLE &&
+ return {BLOG.POST_LIST_STYLE === 'page' ? : } diff --git a/themes/hexo/components/BlogPostListScroll.js b/themes/hexo/components/BlogPostListScroll.js index 569df9ae..2123700d 100644 --- a/themes/hexo/components/BlogPostListScroll.js +++ b/themes/hexo/components/BlogPostListScroll.js @@ -2,7 +2,6 @@ import BLOG from '@/blog.config' import BlogPostCard from './BlogPostCard' import BlogPostListEmpty from './BlogPostListEmpty' import { useGlobal } from '@/lib/global' -import throttle from 'lodash.throttle' import React from 'react' import CONFIG_HEXO from '../config_hexo' import { getListByPage } from '@/lib/utils' @@ -31,13 +30,15 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_HE } // 监听滚动自动分页加载 - const scrollTrigger = React.useCallback(throttle(() => { - const scrollS = window.scrollY + window.outerHeight - const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 - if (scrollS > clientHeight + 100) { - handleGetMore() - } - }, 500)) + const scrollTrigger = () => { + requestAnimationFrame(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }) + } // 监听滚动 React.useEffect(() => { diff --git a/themes/hexo/components/Catalog.js b/themes/hexo/components/Catalog.js index 3252f2ec..880b05d5 100644 --- a/themes/hexo/components/Catalog.js +++ b/themes/hexo/components/Catalog.js @@ -1,5 +1,4 @@ import React, { useRef } from 'react' -import throttle from 'lodash.throttle' import { uuidToId } from 'notion-utils' import Progress from './Progress' import { useGlobal } from '@/lib/global' @@ -28,33 +27,34 @@ const Catalog = ({ toc }) => { // 同步选中目录事件 const [activeSection, setActiveSection] = React.useState(null) - const throttleMs = 100 - const actionSectionScrollSpy = React.useCallback(throttle(() => { - const sections = document.getElementsByClassName('notion-h') - let prevBBox = null - let currentSectionId = activeSection - for (let i = 0; i < sections.length; ++i) { - const section = sections[i] - if (!section || !(section instanceof Element)) continue - if (!currentSectionId) { - currentSectionId = section.getAttribute('data-id') + const actionSectionScrollSpy = () => { + requestAnimationFrame(() => { + const sections = document.getElementsByClassName('notion-h') + let prevBBox = null + let currentSectionId = activeSection + for (let i = 0; i < sections.length; ++i) { + const section = sections[i] + if (!section || !(section instanceof Element)) continue + if (!currentSectionId) { + currentSectionId = section.getAttribute('data-id') + } + const bbox = section.getBoundingClientRect() + const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0 + const offset = Math.max(150, prevHeight / 4) + // GetBoundingClientRect returns values relative to viewport + if (bbox.top - offset < 0) { + currentSectionId = section.getAttribute('data-id') + prevBBox = bbox + continue + } + // No need to continue loop, if last element has been detected + break } - const bbox = section.getBoundingClientRect() - const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0 - const offset = Math.max(150, prevHeight / 4) - // GetBoundingClientRect returns values relative to viewport - if (bbox.top - offset < 0) { - currentSectionId = section.getAttribute('data-id') - prevBBox = bbox - continue - } - // No need to continue loop, if last element has been detected - break - } - setActiveSection(currentSectionId) - const index = tocIds.indexOf(currentSectionId) || 0 - tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' }) - }, throttleMs)) + setActiveSection(currentSectionId) + const index = tocIds.indexOf(currentSectionId) || 0 + tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' }) + }) + } // 无目录就直接返回空 if (!toc || toc.length < 1) { diff --git a/themes/hexo/components/Header.js b/themes/hexo/components/Header.js index 8200a8f4..7f38552e 100644 --- a/themes/hexo/components/Header.js +++ b/themes/hexo/components/Header.js @@ -6,6 +6,7 @@ import NavButtonGroup from './NavButtonGroup' let wrapperTop = 0 let windowTop = 0 let autoScroll = false +const enableAutoScroll = false // 是否开启自动吸附滚动 /** * @@ -16,6 +17,7 @@ const Header = props => { const { siteInfo } = props useEffect(() => { updateHeaderHeight() + if (!typed && window && document.getElementById('typed')) { changeType( new Typed('#typed', { @@ -28,6 +30,7 @@ const Header = props => { }) ) } + if (enableAutoScroll) { scrollTrigger() window.addEventListener('scroll', scrollTrigger) @@ -52,7 +55,7 @@ const Header = props => { return (
+
{ - window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) - }} + onClick={() => { window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) }} className="cursor-pointer w-full text-center py-4 text-3xl absolute bottom-10 text-white" > @@ -80,8 +82,6 @@ const Header = props => { ) } -const enableAutoScroll = false // 是否开启自动吸附滚动 - const autoScrollEnd = () => { if (autoScroll) { windowTop = window.scrollY @@ -93,24 +93,26 @@ const autoScrollEnd = () => { * 自动吸附滚动,移动端体验不好暂时关闭 */ const scrollTrigger = () => { - if (screen.width <= 768) { - return - } + requestAnimationFrame(() => { + if (screen.width <= 768) { + return + } - const scrollS = window.scrollY - // 自动滚动 - if ((scrollS > windowTop) & (scrollS < window.innerHeight) && !autoScroll - ) { - autoScroll = true - window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) - requestAnimationFrame(autoScrollEnd) - } - if ((scrollS < windowTop) && (scrollS < window.innerHeight) && !autoScroll) { - autoScroll = true - window.scrollTo({ top: 0, behavior: 'smooth' }) - requestAnimationFrame(autoScrollEnd) - } - windowTop = scrollS + const scrollS = window.scrollY + // 自动滚动 + if ((scrollS > windowTop) & (scrollS < window.innerHeight) && !autoScroll + ) { + autoScroll = true + window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) + requestAnimationFrame(autoScrollEnd) + } + if ((scrollS < windowTop) && (scrollS < window.innerHeight) && !autoScroll) { + autoScroll = true + window.scrollTo({ top: 0, behavior: 'smooth' }) + requestAnimationFrame(autoScrollEnd) + } + windowTop = scrollS + }) } export default Header diff --git a/themes/hexo/components/JumpToTopButton.js b/themes/hexo/components/JumpToTopButton.js index 427ef500..3602ad99 100644 --- a/themes/hexo/components/JumpToTopButton.js +++ b/themes/hexo/components/JumpToTopButton.js @@ -11,10 +11,11 @@ import CONFIG_HEXO from '../config_hexo' * @constructor */ const JumpToTopButton = ({ showPercent = true, percent }) => { + const { locale } = useGlobal() + if (!CONFIG_HEXO.WIDGET_TO_TOP) { return <> } - const { locale } = useGlobal() return (
window.scrollTo({ top: 0, behavior: 'smooth' })} >
{showPercent && (
{percent}
)} diff --git a/themes/hexo/components/TopNav.js b/themes/hexo/components/TopNav.js index 3aa310ee..4e020cba 100644 --- a/themes/hexo/components/TopNav.js +++ b/themes/hexo/components/TopNav.js @@ -1,5 +1,4 @@ import { useGlobal } from '@/lib/global' -import throttle from 'lodash.throttle' import Link from 'next/link' import { useEffect, useRef, useState } from 'react' import CategoryGroup from './CategoryGroup' @@ -25,37 +24,39 @@ const TopNav = props => { const { isDarkMode } = useGlobal() const router = useRouter() - const scrollTrigger = throttle(() => { - const scrollS = window.scrollY - const nav = document.querySelector('#sticky-nav') - const header = document.querySelector('#header') - const showNav = scrollS <= windowTop || scrollS < 5 || (header && scrollS <= header.clientHeight)// 非首页无大图时影藏顶部 滚动条置顶时隐藏 - // 是否将导航栏透明 - const navTransparent = (scrollS < document.documentElement.clientHeight - 12 && router.route === '/') || scrollS < 300 // 透明导航条的条件 + const scrollTrigger = () => { + requestAnimationFrame(() => { + const scrollS = window.scrollY + const nav = document.querySelector('#sticky-nav') + const header = document.querySelector('#header') + const showNav = scrollS <= windowTop || scrollS < 5 || (header && scrollS <= header.clientHeight)// 非首页无大图时影藏顶部 滚动条置顶时隐藏 + // 是否将导航栏透明 + const navTransparent = (scrollS < document.documentElement.clientHeight - 12 && router.route === '/') || scrollS < 300 // 透明导航条的条件 - if (header && navTransparent) { - nav && nav.classList.replace('bg-white', 'bg-none') - nav && nav.classList.replace('text-black', 'text-white') - nav && nav.classList.replace('border', 'border-transparent') - nav && nav.classList.replace('drop-shadow-md', 'shadow-none') - nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent') - } else { - nav && nav.classList.replace('bg-none', 'bg-white') - nav && nav.classList.replace('text-white', 'text-black') - nav && nav.classList.replace('border-transparent', 'border') - nav && nav.classList.replace('shadow-none', 'drop-shadow-md') - nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray') - } + if (header && navTransparent) { + nav && nav.classList.replace('bg-white', 'bg-none') + nav && nav.classList.replace('text-black', 'text-white') + nav && nav.classList.replace('border', 'border-transparent') + nav && nav.classList.replace('drop-shadow-md', 'shadow-none') + nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent') + } else { + nav && nav.classList.replace('bg-none', 'bg-white') + nav && nav.classList.replace('text-white', 'text-black') + nav && nav.classList.replace('border-transparent', 'border') + nav && nav.classList.replace('shadow-none', 'drop-shadow-md') + nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray') + } - if (!showNav) { - nav && nav.classList.replace('top-0', '-top-20') - windowTop = scrollS - } else { - nav && nav.classList.replace('-top-20', 'top-0') - windowTop = scrollS - } - navDarkMode() - }, 200) + if (!showNav) { + nav && nav.classList.replace('top-0', '-top-20') + windowTop = scrollS + } else { + nav && nav.classList.replace('-top-20', 'top-0') + windowTop = scrollS + } + navDarkMode() + }) + } const navDarkMode = () => { const nav = document.getElementById('sticky-nav') @@ -69,86 +70,85 @@ const TopNav = props => { } } - // 监听滚动 - useEffect(() => { - scrollTrigger() - - window.addEventListener('scroll', scrollTrigger) - return () => { - window.removeEventListener('scroll', scrollTrigger) - } - }, []) - const [isOpen, changeShow] = useState(false) const toggleMenuOpen = () => { changeShow(!isOpen) } + // 监听滚动 + useEffect(() => { + scrollTrigger() + window.addEventListener('scroll', scrollTrigger) + return () => { + window.removeEventListener('scroll', scrollTrigger) + } + }, []) + const searchDrawerSlot = <> - { categories && ( -
-
-
{locale.COMMON.CATEGORY}
- + {categories && ( +
+
+
{locale.COMMON.CATEGORY}
+ - {locale.COMMON.MORE} + {locale.COMMON.MORE} - -
- -
- ) } + +
+ +
+ )} - { tags && ( -
-
-
{locale.COMMON.TAGS}
- + {tags && ( +
+
+
{locale.COMMON.TAGS}
+ - {locale.COMMON.MORE} + {locale.COMMON.MORE} - -
-
- -
-
- ) } + +
+
+ +
+
+ )} return (
- + - {/* 导航栏 */} - ) +
) } export default TopNav diff --git a/themes/matery/LayoutBase.js b/themes/matery/LayoutBase.js index dbd5a488..2b32b468 100644 --- a/themes/matery/LayoutBase.js +++ b/themes/matery/LayoutBase.js @@ -22,18 +22,20 @@ const LayoutBase = props => { const { onLoading } = useGlobal() const scrollListener = () => { - const targetRef = document.getElementById('wrapper') - const clientHeight = targetRef?.clientHeight - const scrollY = window.pageYOffset - const fullHeight = clientHeight - window.outerHeight - let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0)) - if (per > 100) per = 100 - const shouldShow = scrollY > 300 && per > 0 + requestAnimationFrame(() => { + const targetRef = document.getElementById('wrapper') + const clientHeight = targetRef?.clientHeight + const scrollY = window.pageYOffset + const fullHeight = clientHeight - window.outerHeight + let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0)) + if (per > 100) per = 100 + const shouldShow = scrollY > 300 && per > 0 - if (shouldShow !== show) { - switchShow(shouldShow) - } + if (shouldShow !== show) { + switchShow(shouldShow) + } // changePercent(per) + }) } useEffect(() => { document.addEventListener('scroll', scrollListener) diff --git a/themes/matery/components/BlogPostListScroll.js b/themes/matery/components/BlogPostListScroll.js index 105d32db..555e950f 100644 --- a/themes/matery/components/BlogPostListScroll.js +++ b/themes/matery/components/BlogPostListScroll.js @@ -2,7 +2,6 @@ import BLOG from '@/blog.config' import BlogPostCard from './BlogPostCard' import BlogPostListEmpty from './BlogPostListEmpty' import { useGlobal } from '@/lib/global' -import throttle from 'lodash.throttle' import React from 'react' import CONFIG_MATERY from '../config_matery' import { getListByPage } from '@/lib/utils' @@ -31,13 +30,15 @@ const BlogPostListScroll = ({ posts = [], currentSearch, showSummary = CONFIG_MA } // 监听滚动自动分页加载 - const scrollTrigger = React.useCallback(throttle(() => { - const scrollS = window.scrollY + window.outerHeight - const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 - if (scrollS > clientHeight + 100) { - handleGetMore() - } - }, 500)) + const scrollTrigger = () => { + requestAnimationFrame(() => { + const scrollS = window.scrollY + window.outerHeight + const clientHeight = targetRef ? (targetRef.current ? (targetRef.current.clientHeight) : 0) : 0 + if (scrollS > clientHeight + 100) { + handleGetMore() + } + }) + } // 监听滚动 React.useEffect(() => { diff --git a/themes/matery/components/Catalog.js b/themes/matery/components/Catalog.js index a86326e3..9f650f9b 100644 --- a/themes/matery/components/Catalog.js +++ b/themes/matery/components/Catalog.js @@ -1,5 +1,4 @@ import React, { useRef } from 'react' -import throttle from 'lodash.throttle' import { uuidToId } from 'notion-utils' import Progress from './Progress' import { useGlobal } from '@/lib/global' @@ -27,33 +26,34 @@ const Catalog = ({ toc }) => { // 同步选中目录事件 const [activeSection, setActiveSection] = React.useState(null) - const throttleMs = 100 - const actionSectionScrollSpy = React.useCallback(throttle(() => { - const sections = document.getElementsByClassName('notion-h') - let prevBBox = null - let currentSectionId = activeSection - for (let i = 0; i < sections.length; ++i) { - const section = sections[i] - if (!section || !(section instanceof Element)) continue - if (!currentSectionId) { - currentSectionId = section.getAttribute('data-id') + const actionSectionScrollSpy = () => { + requestAnimationFrame(() => { + const sections = document.getElementsByClassName('notion-h') + let prevBBox = null + let currentSectionId = activeSection + for (let i = 0; i < sections.length; ++i) { + const section = sections[i] + if (!section || !(section instanceof Element)) continue + if (!currentSectionId) { + currentSectionId = section.getAttribute('data-id') + } + const bbox = section.getBoundingClientRect() + const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0 + const offset = Math.max(150, prevHeight / 4) + // GetBoundingClientRect returns values relative to viewport + if (bbox.top - offset < 0) { + currentSectionId = section.getAttribute('data-id') + prevBBox = bbox + continue + } + // No need to continue loop, if last element has been detected + break } - const bbox = section.getBoundingClientRect() - const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0 - const offset = Math.max(150, prevHeight / 4) - // GetBoundingClientRect returns values relative to viewport - if (bbox.top - offset < 0) { - currentSectionId = section.getAttribute('data-id') - prevBBox = bbox - continue - } - // No need to continue loop, if last element has been detected - break - } - setActiveSection(currentSectionId) - const index = tocIds.indexOf(currentSectionId) || 0 - tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' }) - }, throttleMs)) + setActiveSection(currentSectionId) + const index = tocIds.indexOf(currentSectionId) || 0 + tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' }) + }) + } // 无目录就直接返回空 if (!toc || toc.length < 1) { diff --git a/themes/matery/components/Header.js b/themes/matery/components/Header.js index 4f954bdd..3f062dde 100644 --- a/themes/matery/components/Header.js +++ b/themes/matery/components/Header.js @@ -5,6 +5,7 @@ import CONFIG_MATERY from '../config_matery' let wrapperTop = 0 let windowTop = 0 let autoScroll = false +const enableAutoScroll = false // 是否开启自动吸附滚动 /** * @@ -28,11 +29,14 @@ const Header = props => { }) ) } - window.addEventListener('scroll', scrollTrigger) - window.addEventListener('resize', updateHeaderHeight) + if (enableAutoScroll) { + scrollTrigger() + window.addEventListener('scroll', scrollTrigger) + } window.addEventListener('resize', updateHeaderHeight) return () => { - window.removeEventListener('scroll', scrollTrigger) - window.removeEventListener('resize', updateHeaderHeight) + if (enableAutoScroll) { + window.removeEventListener('scroll', scrollTrigger) + } window.removeEventListener('resize', updateHeaderHeight) } }) @@ -48,32 +52,34 @@ const Header = props => { * @returns */ const scrollTrigger = () => { - if (screen.width <= 768) { - return - } + requestAnimationFrame(() => { + if (screen.width <= 768) { + return + } - const scrollS = window.scrollY + const scrollS = window.scrollY - // 自动滚动 - if ((scrollS > windowTop) & (scrollS < window.innerHeight) && !autoScroll - ) { - autoScroll = true - window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) - setTimeout(autoScrollEnd, 500) - } - if ((scrollS < windowTop) && (scrollS < window.innerHeight) && !autoScroll) { - autoScroll = true - window.scrollTo({ top: 0, behavior: 'smooth' }) - setTimeout(autoScrollEnd, 500) - } - windowTop = scrollS + // 自动滚动 + if ((scrollS > windowTop) & (scrollS < window.innerHeight) && !autoScroll + ) { + autoScroll = true + window.scrollTo({ top: wrapperTop, behavior: 'smooth' }) + setTimeout(autoScrollEnd, 500) + } + if ((scrollS < windowTop) && (scrollS < window.innerHeight) && !autoScroll) { + autoScroll = true + window.scrollTo({ top: 0, behavior: 'smooth' }) + setTimeout(autoScrollEnd, 500) + } + windowTop = scrollS + }) } function updateHeaderHeight () { - setTimeout(() => { + requestAnimationFrame(() => { const wrapperElement = document.getElementById('wrapper') wrapperTop = wrapperElement?.offsetTop - }, 500) + }) } return ( diff --git a/themes/matery/components/TopNav.js b/themes/matery/components/TopNav.js index 44d524cb..47b485a8 100644 --- a/themes/matery/components/TopNav.js +++ b/themes/matery/components/TopNav.js @@ -1,5 +1,4 @@ import { useGlobal } from '@/lib/global' -import throttle from 'lodash.throttle' import Link from 'next/link' import { useEffect, useRef, useState } from 'react' import CategoryGroup from './CategoryGroup' @@ -23,35 +22,37 @@ const TopNav = props => { const searchDrawer = useRef() const { isDarkMode } = useGlobal() - const scrollTrigger = throttle(() => { - const scrollS = window.scrollY - const nav = document.querySelector('#sticky-nav') - const header = document.querySelector('#header') - const showNav = scrollS <= windowTop || scrollS < 5 // 非首页无大图时影藏顶部 滚动条置顶时隐藏 - // 是否将导航栏透明 - const navTransparent = header && scrollS < 300 // 透明导航条的条件 + const scrollTrigger = () => { + requestAnimationFrame(() => { + const scrollS = window.scrollY + const nav = document.querySelector('#sticky-nav') + const header = document.querySelector('#header') + const showNav = scrollS <= windowTop || scrollS < 5 // 非首页无大图时影藏顶部 滚动条置顶时隐藏 + // 是否将导航栏透明 + const navTransparent = header && scrollS < 300 // 透明导航条的条件 - if (navTransparent) { - nav && nav.classList.replace('bg-indigo-700', 'bg-none') - nav && nav.classList.replace('text-black', 'text-white') - nav && nav.classList.replace('drop-shadow-xl', 'shadow-none') - nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent') - } else { - nav && nav.classList.replace('bg-none', 'bg-indigo-700') - nav && nav.classList.replace('text-white', 'text-black') - nav && nav.classList.replace('shadow-none', 'drop-shadow-xl') - nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray') - } + if (navTransparent) { + nav && nav.classList.replace('bg-indigo-700', 'bg-none') + nav && nav.classList.replace('text-black', 'text-white') + nav && nav.classList.replace('drop-shadow-xl', 'shadow-none') + nav && nav.classList.replace('dark:bg-hexo-black-gray', 'transparent') + } else { + nav && nav.classList.replace('bg-none', 'bg-indigo-700') + nav && nav.classList.replace('text-white', 'text-black') + nav && nav.classList.replace('shadow-none', 'drop-shadow-xl') + nav && nav.classList.replace('transparent', 'dark:bg-hexo-black-gray') + } - if (!showNav) { - nav && nav.classList.replace('top-0', '-top-20') - windowTop = scrollS - } else { - nav && nav.classList.replace('-top-20', 'top-0') - windowTop = scrollS - } - navDarkMode() - }, 200) + if (!showNav) { + nav && nav.classList.replace('top-0', '-top-20') + windowTop = scrollS + } else { + nav && nav.classList.replace('-top-20', 'top-0') + windowTop = scrollS + } + navDarkMode() + }) + } const navDarkMode = () => { const nav = document.getElementById('sticky-nav')