Skip to content

Commit 421a27d

Browse files
authored
Merge pull request tangly1024#2474 from tangly1024/hexo/jump-random
hexo 微调,添加随机跳转按钮
2 parents eead53d + 73a4e26 commit 421a27d

9 files changed

+133
-42
lines changed

themes/hexo/components/FloatDarkModeButton.js themes/hexo/components/ButtonFloatDarkMode.js

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import { siteConfig } from '@/lib/config'
12
import { useGlobal } from '@/lib/global'
23
import { saveDarkModeToLocalStorage } from '@/themes/theme'
34
import CONFIG from '../config'
4-
import { siteConfig } from '@/lib/config'
55

6-
export default function FloatDarkModeButton () {
6+
/**
7+
* 深色模式按钮
8+
*/
9+
export default function ButtonDarkModeFloat() {
710
const { isDarkMode, updateDarkMode } = useGlobal()
811

912
if (!siteConfig('HEXO_WIDGET_DARK_MODE', null, CONFIG)) {
@@ -23,10 +26,13 @@ export default function FloatDarkModeButton () {
2326
return (
2427
<div
2528
onClick={handleChangeDarkMode}
26-
className={'justify-center items-center w-7 h-7 text-center transform hover:scale-105 duration-200'
27-
}
28-
>
29-
<i id="darkModeButton" className={`${isDarkMode ? 'fa-sun' : 'fa-moon'} fas text-xs`}/>
29+
className={
30+
'justify-center items-center w-7 h-7 text-center transform hover:scale-105 duration-200'
31+
}>
32+
<i
33+
id='darkModeButton'
34+
className={`${isDarkMode ? 'fa-sun' : 'fa-moon'} fas text-xs`}
35+
/>
3036
</div>
3137
)
3238
}
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
1-
import CONFIG from '../config'
21
import { siteConfig } from '@/lib/config'
2+
import CONFIG from '../config'
33

44
/**
55
* 跳转到评论区
66
* @returns {JSX.Element}
77
* @constructor
88
*/
9-
const JumpToCommentButton = () => {
9+
const ButtonJumpToComment = () => {
1010
if (!siteConfig('HEXO_WIDGET_TO_COMMENT', null, CONFIG)) {
1111
return <></>
1212
}
1313

1414
function navToComment() {
1515
if (document.getElementById('comment')) {
16-
window.scrollTo({ top: document.getElementById('comment').offsetTop, behavior: 'smooth' })
16+
window.scrollTo({
17+
top: document.getElementById('comment').offsetTop,
18+
behavior: 'smooth'
19+
})
1720
}
1821
// 兼容性不好
1922
// const commentElement = document.getElementById('comment')
2023
// if (commentElement) {
2124
// commentElement?.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })
2225
}
2326

24-
return (<div className='flex space-x-1 items-center justify-center transform hover:scale-105 duration-200 w-7 h-7 text-center' onClick={navToComment} >
25-
<i className='fas fa-comment text-xs' />
26-
</div>)
27+
return (
28+
<div
29+
className='flex space-x-1 items-center justify-center transform hover:scale-105 duration-200 w-7 h-7 text-center'
30+
onClick={navToComment}>
31+
<i className='fas fa-comment text-xs' />
32+
</div>
33+
)
2734
}
2835

29-
export default JumpToCommentButton
36+
export default ButtonJumpToComment

themes/hexo/components/JumpToTopButton.js themes/hexo/components/ButtonJumpToTop.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import { siteConfig } from '@/lib/config'
12
import { useGlobal } from '@/lib/global'
23
import CONFIG from '../config'
3-
import { siteConfig } from '@/lib/config'
44

55
/**
66
* 跳转到网页顶部
@@ -10,7 +10,7 @@ import { siteConfig } from '@/lib/config'
1010
* @returns {JSX.Element}
1111
* @constructor
1212
*/
13-
const JumpToTopButton = ({ showPercent = true, percent }) => {
13+
const ButtonJumpToTop = ({ showPercent = true, percent }) => {
1414
const { locale } = useGlobal()
1515

1616
if (!siteConfig('HEXO_WIDGET_TO_TOP', null, CONFIG)) {
@@ -22,4 +22,4 @@ const JumpToTopButton = ({ showPercent = true, percent }) => {
2222
</div>)
2323
}
2424

25-
export default JumpToTopButton
25+
export default ButtonJumpToTop
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { siteConfig } from '@/lib/config'
2+
import { useGlobal } from '@/lib/global'
3+
import { useRouter } from 'next/router'
4+
5+
/**
6+
* 随机跳转到一个文章
7+
*/
8+
export default function ButtonRandomPost(props) {
9+
const { latestPosts } = props
10+
const router = useRouter()
11+
const { locale } = useGlobal()
12+
/**
13+
* 随机跳转文章
14+
*/
15+
function handleClick() {
16+
const randomIndex = Math.floor(Math.random() * latestPosts.length)
17+
const randomPost = latestPosts[randomIndex]
18+
router.push(`${siteConfig('SUB_PATH', '')}/${randomPost?.slug}`)
19+
}
20+
21+
return (
22+
<div
23+
title={locale.MENU.WALK_AROUND}
24+
className='cursor-pointer hover:bg-black hover:bg-opacity-10 rounded-full w-10 h-10 flex justify-center items-center duration-200 transition-all'
25+
onClick={handleClick}>
26+
<i className='fa-solid fa-podcast'></i>
27+
</div>
28+
)
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { siteConfig } from '@/lib/config'
2+
import { useGlobal } from '@/lib/global'
3+
import { useRouter } from 'next/router'
4+
5+
/**
6+
* 随机跳转到一个文章
7+
*/
8+
export default function ButtonRandomPostMini(props) {
9+
const { latestPosts } = props
10+
const router = useRouter()
11+
const { locale } = useGlobal()
12+
/**
13+
* 随机跳转文章
14+
*/
15+
function handleClick() {
16+
const randomIndex = Math.floor(Math.random() * latestPosts.length)
17+
const randomPost = latestPosts[randomIndex]
18+
router.push(`${siteConfig('SUB_PATH', '')}/${randomPost?.slug}`)
19+
}
20+
21+
return (
22+
<div
23+
title={locale.MENU.WALK_AROUND}
24+
className='flex space-x-1 items-center justify-center transform hover:scale-105 duration-200 w-7 h-7 text-center'
25+
onClick={handleClick}>
26+
<i className='fa-solid fa-podcast'></i>
27+
</div>
28+
)
29+
}

themes/hexo/components/Header.js

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Link from 'next/link'
55
import { useRouter } from 'next/router'
66
import { useCallback, useEffect, useRef, useState } from 'react'
77
import CONFIG from '../config'
8+
import ButtonRandomPost from './ButtonRandomPost'
89
import CategoryGroup from './CategoryGroup'
910
import Logo from './Logo'
1011
import { MenuListTop } from './MenuListTop'
@@ -28,6 +29,7 @@ const Header = props => {
2829
const router = useRouter()
2930
const [isOpen, changeShow] = useState(false)
3031
const showSearchButton = siteConfig('HEXO_MENU_SEARCH', false, CONFIG)
32+
const showRandomButton = siteConfig('HEXO_MENU_RANDOM', false, CONFIG)
3133

3234
const toggleMenuOpen = () => {
3335
changeShow(!isOpen)
@@ -172,6 +174,7 @@ const Header = props => {
172174
)}
173175
</div>
174176
{showSearchButton && <SearchButton />}
177+
{showRandomButton && <ButtonRandomPost {...props} />}
175178
</div>
176179
</div>
177180
</div>
+29-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import throttle from 'lodash.throttle'
22
import { useCallback, useEffect, useState } from 'react'
3-
import FloatDarkModeButton from './FloatDarkModeButton'
4-
import JumpToTopButton from './JumpToTopButton'
3+
import ButtonDarkModeFloat from './ButtonFloatDarkMode'
4+
import ButtonJumpToTop from './ButtonJumpToTop'
55

66
/**
77
* 悬浮在右下角的按钮,当页面向下滚动100px时会出现
@@ -10,33 +10,40 @@ import JumpToTopButton from './JumpToTopButton'
1010
*/
1111
export default function RightFloatArea({ floatSlot }) {
1212
const [showFloatButton, switchShow] = useState(false)
13-
const scrollListener = useCallback(throttle(() => {
14-
const targetRef = document.getElementById('wrapper')
15-
const clientHeight = targetRef?.clientHeight
16-
const scrollY = window.pageYOffset
17-
const fullHeight = clientHeight - window.outerHeight
18-
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
19-
if (per > 100) per = 100
20-
const shouldShow = scrollY > 100 && per > 0
13+
const scrollListener = useCallback(
14+
throttle(() => {
15+
const targetRef = document.getElementById('wrapper')
16+
const clientHeight = targetRef?.clientHeight
17+
const scrollY = window.pageYOffset
18+
const fullHeight = clientHeight - window.outerHeight
19+
let per = parseFloat(((scrollY / fullHeight) * 100).toFixed(0))
20+
if (per > 100) per = 100
21+
const shouldShow = scrollY > 100 && per > 0
2122

22-
// 右下角显示悬浮按钮
23-
if (shouldShow !== showFloatButton) {
24-
switchShow(shouldShow)
25-
}
26-
}, 200))
23+
// 右下角显示悬浮按钮
24+
if (shouldShow !== showFloatButton) {
25+
switchShow(shouldShow)
26+
}
27+
}, 200)
28+
)
2729

2830
useEffect(() => {
2931
document.addEventListener('scroll', scrollListener)
3032
return () => document.removeEventListener('scroll', scrollListener)
3133
}, [])
3234

3335
return (
34-
<div className={(showFloatButton ? 'opacity-100 ' : 'invisible opacity-0') + ' duration-300 transition-all bottom-12 right-1 fixed justify-end z-20 text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm'}>
35-
<div className={'justify-center flex flex-col items-center cursor-pointer'}>
36-
<FloatDarkModeButton />
37-
{floatSlot}
38-
<JumpToTopButton />
39-
</div>
40-
</div>
36+
<div
37+
className={
38+
(showFloatButton ? 'opacity-100 ' : 'invisible opacity-0') +
39+
' duration-300 transition-all bottom-12 right-1 fixed justify-end z-20 text-white bg-indigo-500 dark:bg-hexo-black-gray rounded-sm'
40+
}>
41+
<div
42+
className={'justify-center flex flex-col items-center cursor-pointer'}>
43+
<ButtonDarkModeFloat />
44+
{floatSlot}
45+
<ButtonJumpToTop />
46+
</div>
47+
</div>
4148
)
4249
}

themes/hexo/config.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
const CONFIG = {
22
HEXO_HOME_BANNER_ENABLE: true,
33
// 3.14.1以后的版本中,欢迎语在blog.config.js中配置,用英文逗号','隔开多个。
4-
HEXO_HOME_BANNER_GREETINGS: ['Hi,我是一个程序员', 'Hi,我是一个打工人', 'Hi,我是一个干饭人', '欢迎来到我的博客🎉'], // 首页大图标语文字
4+
HEXO_HOME_BANNER_GREETINGS: [
5+
'Hi,我是一个程序员',
6+
'Hi,我是一个打工人',
7+
'Hi,我是一个干饭人',
8+
'欢迎来到我的博客🎉'
9+
], // 首页大图标语文字
510

611
HEXO_HOME_NAV_BUTTONS: true, // 首页是否显示分类大图标按钮
712
// 已知未修复bug, 在移动端开启true后会加载不出图片; 暂时建议设置为false。
@@ -15,6 +20,7 @@ const CONFIG = {
1520
HEXO_MENU_TAG: true, // 显示标签
1621
HEXO_MENU_ARCHIVE: true, // 显示归档
1722
HEXO_MENU_SEARCH: true, // 显示搜索
23+
HEXO_MENU_RANDOM: true, // 显示随机跳转按钮
1824

1925
HEXO_POST_LIST_COVER: true, // 列表显示文章封面
2026
HEXO_POST_LIST_COVER_HOVER_ENLARGE: false, // 列表鼠标悬停放大

themes/hexo/index.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ import ArticleRecommend from './components/ArticleRecommend'
1717
import BlogPostArchive from './components/BlogPostArchive'
1818
import BlogPostListPage from './components/BlogPostListPage'
1919
import BlogPostListScroll from './components/BlogPostListScroll'
20+
import ButtonJumpToComment from './components/ButtonJumpToComment'
21+
import ButtonRandomPostMini from './components/ButtonRandomPostMini'
2022
import Card from './components/Card'
2123
import Footer from './components/Footer'
2224
import Header from './components/Header'
2325
import Hero from './components/Hero'
24-
import JumpToCommentButton from './components/JumpToCommentButton'
2526
import PostHero from './components/PostHero'
2627
import RightFloatArea from './components/RightFloatArea'
2728
import SearchNav from './components/SearchNav'
@@ -51,8 +52,9 @@ export const useHexoGlobal = () => useContext(ThemeGlobalHexo)
5152
const LayoutBase = props => {
5253
const { post, children, slotTop, className } = props
5354
const { onLoading, fullWidth } = useGlobal()
54-
5555
const router = useRouter()
56+
const showRandomButton = siteConfig('HEXO_MENU_RANDOM', false, CONFIG)
57+
5658
const headerSlot = post ? (
5759
<PostHero {...props} />
5860
) : router.route === '/' &&
@@ -63,6 +65,7 @@ const LayoutBase = props => {
6365
const drawerRight = useRef(null)
6466
const tocRef = isBrowser ? document.getElementById('article-wrapper') : null
6567

68+
// 悬浮按钮内容
6669
const floatSlot = (
6770
<>
6871
{post?.toc?.length > 1 && (
@@ -74,7 +77,8 @@ const LayoutBase = props => {
7477
/>
7578
</div>
7679
)}
77-
{post && <JumpToCommentButton />}
80+
{post && <ButtonJumpToComment />}
81+
{showRandomButton && <ButtonRandomPostMini {...props} />}
7882
</>
7983
)
8084

0 commit comments

Comments
 (0)