mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-20 23:16:49 +00:00
目录自动滚动细节
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { getGlobalData, getPost, getPostBlocks } from '@/lib/db/getSiteData'
|
||||
import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents'
|
||||
import { uploadDataToAlgolia } from '@/lib/plugins/algolia'
|
||||
import { checkSlugHasMorThanTwoSlash, getRecommendPost } from '@/lib/utils/post'
|
||||
import { idToUuid } from 'notion-utils'
|
||||
@@ -97,6 +98,15 @@ export async function getStaticProps({
|
||||
if (!props?.post?.blockMap) {
|
||||
props.post.blockMap = await getPostBlocks(props.post.id, from)
|
||||
}
|
||||
|
||||
// 目录默认加载
|
||||
if (props.post?.blockMap?.block) {
|
||||
props.post.content = Object.keys(props.post.blockMap.block).filter(
|
||||
key => props.post.blockMap.block[key]?.value?.parent_id === props.post.id
|
||||
)
|
||||
props.post.toc = getPageTableOfContents(props.post, props.post.blockMap)
|
||||
}
|
||||
|
||||
// 生成全文索引 && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA)
|
||||
if (BLOG.ALGOLIA_APP_ID) {
|
||||
uploadDataToAlgolia(props?.post)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import BLOG from '@/blog.config'
|
||||
import { siteConfig } from '@/lib/config'
|
||||
import { getGlobalData, getPost, getPostBlocks } from '@/lib/db/getSiteData'
|
||||
import { getPageTableOfContents } from '@/lib/notion/getPageTableOfContents'
|
||||
import { uploadDataToAlgolia } from '@/lib/plugins/algolia'
|
||||
import { checkSlugHasOneSlash, getRecommendPost } from '@/lib/utils/post'
|
||||
import { idToUuid } from 'notion-utils'
|
||||
@@ -86,6 +87,15 @@ export async function getStaticProps({ params: { prefix, slug }, locale }) {
|
||||
if (!props?.post?.blockMap) {
|
||||
props.post.blockMap = await getPostBlocks(props.post.id, from)
|
||||
}
|
||||
|
||||
// 目录默认加载
|
||||
if (props.post?.blockMap?.block) {
|
||||
props.post.content = Object.keys(props.post.blockMap.block).filter(
|
||||
key => props.post.blockMap.block[key]?.value?.parent_id === props.post.id
|
||||
)
|
||||
props.post.toc = getPageTableOfContents(props.post, props.post.blockMap)
|
||||
}
|
||||
|
||||
// 生成全文索引 && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA)
|
||||
if (BLOG.ALGOLIA_APP_ID) {
|
||||
uploadDataToAlgolia(props?.post)
|
||||
|
||||
@@ -55,12 +55,6 @@ const Slug = props => {
|
||||
setLock(true)
|
||||
} else {
|
||||
setLock(false)
|
||||
if (!lock && post?.blockMap?.block) {
|
||||
post.content = Object.keys(post.blockMap.block).filter(
|
||||
key => post.blockMap.block[key]?.value?.parent_id === post.id
|
||||
)
|
||||
post.toc = getPageTableOfContents(post, post.blockMap)
|
||||
}
|
||||
}
|
||||
|
||||
// 读取上次记录 自动提交密码
|
||||
@@ -171,6 +165,14 @@ export async function getStaticProps({ params: { prefix }, locale }) {
|
||||
props.post.blockMap = await getPostBlocks(props.post.id, from)
|
||||
}
|
||||
|
||||
// 目录默认加载
|
||||
if (props.post?.blockMap?.block) {
|
||||
props.post.content = Object.keys(props.post.blockMap.block).filter(
|
||||
key => props.post.blockMap.block[key]?.value?.parent_id === props.post.id
|
||||
)
|
||||
props.post.toc = getPageTableOfContents(props.post, props.post.blockMap)
|
||||
}
|
||||
|
||||
// 生成全文索引 && process.env.npm_lifecycle_event === 'build' && JSON.parse(BLOG.ALGOLIA_RECREATE_DATA)
|
||||
if (BLOG.ALGOLIA_APP_ID) {
|
||||
uploadDataToAlgolia(props?.post)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import throttle from 'lodash.throttle'
|
||||
import { uuidToId } from 'notion-utils'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import Progress from './Progress'
|
||||
|
||||
/**
|
||||
@@ -9,7 +9,7 @@ import Progress from './Progress'
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
const Catalog = ({ toc, className }) => {
|
||||
const Catalog = ({ post, toc, className }) => {
|
||||
const tocIds = []
|
||||
|
||||
// 目录自动滚动
|
||||
@@ -19,43 +19,45 @@ const Catalog = ({ toc, className }) => {
|
||||
|
||||
// 监听滚动事件
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', actionSectionScrollSpy)
|
||||
actionSectionScrollSpy()
|
||||
if (toc && toc.length > 1) {
|
||||
actionSectionScrollSpy()
|
||||
window.addEventListener('scroll', actionSectionScrollSpy)
|
||||
}
|
||||
setTimeout(() => {
|
||||
console.log('目录', post, toc)
|
||||
}, 1000)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', actionSectionScrollSpy)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const throttleMs = 200
|
||||
const actionSectionScrollSpy = 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 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 actionSectionScrollSpy = 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')
|
||||
}
|
||||
setActiveSection(currentSectionId)
|
||||
const index = tocIds.indexOf(currentSectionId) || 0
|
||||
tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
|
||||
console.log(tRef?.current)
|
||||
}, throttleMs)
|
||||
)
|
||||
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)
|
||||
|
||||
// 无目录就直接返回空
|
||||
if (!toc || toc.length < 1) {
|
||||
@@ -68,10 +70,10 @@ const Catalog = ({ toc, className }) => {
|
||||
<Progress />
|
||||
</div>
|
||||
<div
|
||||
className='overflow-y-auto scroll-hidden lg:max-h-dvh max-h-44'
|
||||
className='overflow-y-auto scroll-hidden lg:max-h-96 max-h-44'
|
||||
ref={tRef}>
|
||||
<nav className='h-full text-black'>
|
||||
{toc.map(tocItem => {
|
||||
{toc?.map(tocItem => {
|
||||
const id = uuidToId(tocItem.id)
|
||||
tocIds.push(id)
|
||||
return (
|
||||
|
||||
@@ -189,7 +189,11 @@ const LayoutSlug = props => {
|
||||
{/* 文章区块分为三列 */}
|
||||
<div className='grid grid-cols-1 lg:grid-cols-5 gap-8 py-12'>
|
||||
<div className='h-full lg:col-span-1 hidden lg:block'>
|
||||
<Catalog toc={post?.toc} className='sticky top-20' />
|
||||
<Catalog
|
||||
post={post}
|
||||
toc={post?.toc || []}
|
||||
className='sticky top-20'
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Notion文章主体 */}
|
||||
|
||||
Reference in New Issue
Block a user