Fluid自定义右键菜单
前言
本期美化同样贯彻了前两期美化的原则:无侵入式美化,即不修改主题的源代码,只通过修改配置文件、自定义样式以及Hexo注入器来实现美化。前两期的美化可以点击下方的链接卡片查看。
在本期中,我们将实现一个自定义的右键菜单,我参考了苍岚和loyeh两位博主的实现方式,在他们的基础上进行了改进和扩展,最终实现了一个更加美观和实用的右键菜单。如果不关心实现,可以直接跳转至 总结 获取实现代码和使用方法。
功能设计
在设计这个右键菜单时,我主要考虑了我个人的使用习惯,兼顾访客可能存在的需求。最终,我设计了以下功能:
- 在覆盖浏览器原本的右键菜单时,必须留有使用浏览器原生右键菜单的入口。
- 提供常用的功能,如前进、后退、刷新等
- 提供快速返回顶部和快速跳转到页脚的功能
- 应对各种情况做出不同的响应,如:
- 选中文本时,提供复制文本、必应搜索等功能
- 在图片上,提供复制图片链接、下载图片等功能
- 在链接上,提供打开链接等功能
- 常驻功能中,提供复制当前页面链接的功能和切换主题昼夜模式的功能
- 提供站内搜索、快速访问博客分类和文章标签的入口
- 为访客提供随机访问文章的功能
综上,我们只需要依次设计实现这些功能即可。
实现步骤
- 创建右键菜单的 HTML 结构
- 使用 Hexo 注入器将 HTML 结构注入到页面中
- 使用 CSS 美化右键菜单
- 使用 JavaScript 实现右键菜单的显示与隐藏
- 使用 JavaScript 实现右键菜单的各项功能
创建右键菜单的 HTML 结构
在 Hexo 的 source/html 目录下创建一个
RightMenu.html 文件,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<div id="tooltip-rightmenu" class="tooltip-rightmenu">如需原始右键菜单请按下 <strong>Ctrl+右键</strong></div>
<div id="tooltip-rightmenu-return" class="tooltip-rightmenu"></div>
<div id="rightmenu-wrapper">
<ul class="list-v rightmenu" id="rightmenu-content">
<li class="navigation menuNavigation-Content">
<a class="nav icon-only fix-cursor-default" aria-label="back" onclick="history.back()"><i class="fa-solid fa-chevron-left"></i></a>
<a class="nav icon-only fix-cursor-default" aria-label="forward" onclick="history.forward()"><i class="fa-solid fa-chevron-right"></i></a>
<a class="nav icon-only fix-cursor-default" aria-label="reload" onclick="window.location.reload()"><i class="fa-solid fa-rotate-right"></i></a>
<a class="nav icon-only fix-cursor-default" aria-label="top" onclick="scrollToTopSmooth();"><i class="fa-solid fa-chevron-up"></i></a>
<a class="nav icon-only fix-cursor-default" aria-label="bottom" onclick="scrollToBottomSmooth();"><i class="fa-solid fa-chevron-down"></i></a>
</li>
<hr class="menuLoad-Content" style="display: block;" id="top-line" hidden>
<li class="menuLoad-Content" style="display: block;" id="copy-selected-text" hidden>
<a class="vlts-menu fix-cursor-default" target="_self" onclick="copySelectedText();">
<span>
<i class="fa-solid fa-copy"></i>
复制选中
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;" id="search-selected-text-BING" hidden>
<a class="vlts-menu fix-cursor-default" target="_blank" onclick="searchSelectedTextBing();">
<span>
<i class="fa-solid fa-magnifying-glass-arrow-right"></i>
必应搜索
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;" id="go-to-link" hidden>
<a class="vlts-menu fix-cursor-default" target="_blank">
<span>
<i class="fa-solid fa-arrow-up-right-from-square"></i>
转到链接
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;" id="download-image" hidden>
<a class="vlts-menu fix-cursor-default" target="_self" onclick="downloadImage();">
<span>
<i class="fa-solid fa-image"></i>
下载图片
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;" id="copy-image-link" hidden>
<a class="vlts-menu fix-cursor-default" target="_self" onclick="copyImageLink();">
<span>
<i class="fa-solid fa-link"></i>
复制图片链接
</span>
</a>
</li>
<hr class="menuLoad-Content" style="display: block;">
<li class="menuLoad-Content" style="display: block;">
<a class="vlts-menu fix-cursor-default" target="_self" onclick="RandomGo()">
<span>
<i class="fa-solid fa-paper-plane"></i>
随便看看
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;">
<a class="vlts-menu fix-cursor-default" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
<span>
<i class="fa-solid fa-magnifying-glass"></i>
站内搜索
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;">
<a class="vlts-menu fix-cursor-default" target="_self" href="/categories/">
<span>
<i class="iconfont icon-category-fill"></i>
博客分类
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;">
<a class="vlts-menu fix-cursor-default" target="_self" href="/tags/">
<span>
<i class="fa-solid fa-tags"></i>
文章标签
</span>
</a>
</li>
<hr class="menuLoad-Content" style="display: block;">
<li class="menuLoad-Content" style="display: block;">
<a class="vlts-menu fix-cursor-default" target="_self" onclick="copyLink();">
<span>
<i class="fa-solid fa-copy"></i>
复制链接
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;">
<a class="vlts-menu fix-cursor-default" target="_self" onclick="toggleColorMode();">
<span>
<i id="toggle-color-mode-icon" class="fa-solid fa-circle-half-stroke"></i>
切换昼夜
</span>
</a>
</li>
<li class="menuLoad-Content" style="display: block;">
<a class="vlts-menu fix-cursor-default" target="_self" onclick="toggleBackgroundMode();">
<span>
<i id="toggle-background-mode-icon" class="fa-solid fa-toggle-on"></i>
全屏背景
</span>
</a>
</li>
</ul>
</div>
<script src="/js/RightMenu.js" type="text/javascript"></script>
<link href="/css/RightMenu.css" type="text/css" rel="stylesheet"/>其中 tooltip-rightmenu 和
tooltip-rightmenu-return
是用于提示用户如何使用右键菜单的元素,rightmenu-wrapper
是右键菜单的容器,rightmenu-content
是右键菜单的内容列表,也是我们需要实现的功能项。
在代码的最后,我们引入了 RightMenu.js 和
RightMenu.css
文件,这两个文件将分别用于实现右键菜单的逻辑和样式,因此我们不必在
_config.fluid.yml 中再进行额外的配置。
使用 Hexo 注入器将 HTML 结构注入到页面中
在 Hexo 的 scripts/injector.js 文件中添加以下代码:
1
2
3
4
hexo.extend.filter.register('theme_inject', function(injects) {
// 右键菜单
injects.bodyBegin.file('default', "source/html/RightMenu.html");
});这段代码将 RightMenu.html 文件注入到页面的
<body> 标签开始的位置。这样,当页面加载时,右键菜单的
HTML 结构就会被插入到页面中。
使用 CSS 美化右键菜单
接下来我们将实现右键菜单的样式。在 source/css
目录下创建一个 RightMenu.css 文件,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
div#rightmenu-wrapper {
display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
display: none;
position: fixed;
z-index: 2147483648;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
ul.list-v.rightmenu {
display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
display: block;
background-color: var(--body-bg-color);
opacity: 0.9;
max-width: 240px;
overflow: hidden;
}
ul.list-v {
z-index: 1;
display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
display: none;
position: absolute;
box-shadow: 0 12px 4px 0px rgba(0,0,0,0.8), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
-webkit-box-shadow: 0 2px 4px 0px rgba(0,0,0,0.08), 0 4px 8px 0px rgba(0,0,0,0.08), 0 8px 16px 0px rgba(0,0,0,0.08);
margin-top: -6px;
border-radius: 4px;
-webkit-border-radius: 4px;
padding: 8px 0;
}
ul.list-v.rightmenu li.navigation, ul.list-v.rightmenu li.music {
display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
display: -ms-flexbox /* TWEENER - IE 10 */;
display: -webkit-flex /* NEW - Chrome */;
display: flex /* NEW, Spec - Opera 12.1, Firefox 20+ */;
display: flex;
margin: 0 12px 0 12px;
justify-content: space-between;
-webkit-justify-content: space-between;
-khtml-justify-content: space-between;
-moz-justify-content: space-between;
-o-justify-content: space-between;
-ms-justify-content: space-between;
}
ul.list-v >li {
white-space: nowrap;
word-break: keep-all;
}
ul.list-v hr {
margin-top: 8px;
margin-bottom: 8px;
}
ul.list-v.rightmenu li.navigation a.nav i, ul.list-v.rightmenu li.music a.nav i {
margin: 0;
width: 16px;
line-height: 32px;
}
ul.list-v >li {
white-space: nowrap;
word-break: keep-all;
}
ul.list-v.rightmenu a.vlts-menu {
text-overflow: ellipsis;
overflow: hidden;
line-height: 36px;
font-weight: normal;
margin-left: 10px;
transition: all 0.4s ease;
}
ul.list-v.rightmenu a.vlts-menu:hover {
padding-left: 30px;
}
.rightmenu-icon{
margin: 0 110px 0 8px;
}
ul.list-v >li>a {
transition: all 0.28s ease;
-webkit-transition: all 0.28s ease;
-khtml-transition: all 0.28s ease;
-moz-transition: all 0.28s ease;
-o-transition: all 0.28s ease;
-ms-transition: all 0.28s ease;
display: -webkit-box /* OLD - iOS 6-, Safari 3.1-6 */;
display: -moz-box /* OLD - Firefox 19- (buggy but mostly works) */;
display: block;
color: var(--text-color);
font-size: 1rem;
font-weight: bold;
line-height: 36px;
padding: 0 8px 0 8px;
text-overflow: ellipsis;
border-radius: 4px;
-webkit-border-radius: 4px;
}
ul.list-v >li>a :hover{
color: var(--link-hover-color)
}
ul.list-v.rightmenu a {
cursor: default;
}
/* 信息提示框 */
:root {
--tooltip-bg-color: #181c27a4;
--tooltip-text-color: #eeeeee;
}
[data-user-color-scheme="dark"] {
--tooltip-bg-color: #eeeeeea4;
--tooltip-text-color: #181c27;
}
.tooltip-rightmenu {
position: fixed;
top: 13%;
left: 50%;
transform: translate(-50%, -50%); /* 居中 */
background: var(--tooltip-bg-color);
color: var(--tooltip-text-color);
padding: 10px 25px;
border-radius: 5px;
opacity: 0;
z-index: 99;
transition: opacity 1s ease-in-out;
}
.show-tooltip {
opacity: 0.8;
}如果你想要更改右键菜单的样式,可以借助浏览器的开发者工具选择对应的元素,修改其 CSS 属性。
使用 JavaScript 实现右键菜单的显示与隐藏
为了让我们自定义的右键菜单能够在用户右键点击时显示,我们需要使用
JavaScript 来实现这一功能。在 source/js 目录下创建一个
RightMenu.js 文件,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 右键菜单
var right_click_num = 0;
var rect = document.getElementById("rightmenu-content").getBoundingClientRect();
window.oncontextmenu = function(e){
// 检查是否按下了Ctrl键
if (e.ctrlKey) {
return true;
}
e.preventDefault(); //阻止浏览器自带的右键菜单显示
var menu = document.getElementById("rightmenu-wrapper");
menu.style.display = "block"; //将自定义的“右键菜单”显示出来
if (e.clientX + rect.width > window.innerWidth) { // 如果超出屏幕右边
if (e.clientX - rect.width < 0) {
menu.style.left = "0px"; // 如果超出屏幕左边,则调整位置到左侧贴边
} else {
menu.style.left = e.clientX - rect.width + "px"; // 否则调整到鼠标位置的左侧
}
} else {
menu.style.left = e.clientX + "px"; // 设置位置,跟随鼠标
}
if (e.clientY + rect.height > window.innerHeight) { // 如果超出屏幕底部
if (e.clientY - rect.height < 0) {
menu.style.top = "0px"; // 如果超出屏幕顶部,则调整位置到顶部
} else {
menu.style.top = e.clientY - rect.height + "px"; // 否则调整到鼠标位置的上方
}
} else {
menu.style.top = e.clientY + "px"; // 设置位置,跟随鼠标
}
right_click_num = right_click_num + 1; //右键点击次数加1
if(right_click_num == 1){
const tooltip = document.getElementById('tooltip-rightmenu');
tooltip.classList.add('show-tooltip');
// 3秒后隐藏提示框
setTimeout(() => {
tooltip.classList.remove('show-tooltip');
}, 3000);
}
}
window.onclick = function(e){ //点击窗口,右键菜单隐藏
var menu = document.getElementById("rightmenu-wrapper");
menu.style.display = "none";
}这样,我们就实现了一个基本的右键菜单显示与隐藏功能。当用户右键点击时,自定义的右键菜单会显示在鼠标位置,并且如果用户按下了
Ctrl 键,则会显示浏览器原生的右键菜单。
使用 JavaScript 实现右键菜单的各项功能
在上一步中,我们已经实现了右键菜单的显示与隐藏功能,但其中的部分选项仍旧是一个空壳。接下来,我们将为这些选项添加功能。同样是在
RightMenu.js 文件中,我们将添加以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// 监听鼠标右键按下事件
document.addEventListener('contextmenu', function(event) {
// 检查是否有选中的文本
const copySelectedTextItem = document.getElementById('copy-selected-text');
const searchSelectedTextItem = document.getElementById('search-selected-text-BING');
const selectedText = window.getSelection().toString().trim();
if (selectedText) {
copySelectedTextItem.hidden = false;
searchSelectedTextItem.hidden = false;
} else {
copySelectedTextItem.hidden = true;
searchSelectedTextItem.hidden = true;
}
// 检查是否有链接被点击
const goToLinkItem = document.getElementById('go-to-link');
const link = event.target.closest('a[href]');
if (link) {
goToLinkItem.hidden = false;
goToLinkItem.querySelector('a').setAttribute('href', link.href);
} else {
goToLinkItem.hidden = true;
}
//检查是否有图片被点击
const downloadImageItem = document.getElementById('download-image');
const copyImageItem = document.getElementById('copy-image-link');
const img = event.target.closest('img') || event.target.closest('svg');
if (img) {
downloadImageItem.hidden = false;
if (img.tagName.toLowerCase() === 'img') {
copyImageItem.hidden = false;
downloadImageItem.querySelector('a').setAttribute('onclick', `downloadImage('${img.src}')`);
copyImageItem.querySelector('a').setAttribute('onclick', `copyImageLink('${img.src}')`);
} else if (img.tagName.toLowerCase() === 'svg' && img.classList.contains('custom-gallery-svg')) {
const backgroundImage = img.style.backgroundImage;
const urlMatch = backgroundImage.match(/url\(["']?(.*?)["']?\)/);
if (urlMatch && urlMatch[1]) {
const imageUrl = urlMatch[1];
downloadImageItem.querySelector('a').setAttribute('onclick', `downloadImage('${imageUrl}')`);
copyImageItem.querySelector('a').setAttribute('onclick', `copyImageLink('${imageUrl}')`);
}
}
} else {
downloadImageItem.hidden = true;
copyImageItem.hidden = true;
}
// 根据前三者判断第一栏是否有元素,需要分割线
const topLineItem = document.getElementById('top-line');
if (copySelectedTextItem.hidden && !link && !img) {
topLineItem.hidden = true;
} else {
topLineItem.hidden = false;
}
// 更新尺寸相关参数
rect = document.getElementById("rightmenu-content").getBoundingClientRect();
});
// 平滑滚动到顶部
function scrollToTopSmooth() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
// 平滑滚动到底部
function scrollToBottomSmooth() {
window.scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth'
});
}
// 复制选中-复制选中文本功能
function copySelectedText() {
const selectedText = window.getSelection().toString();
if (selectedText) {
navigator.clipboard.writeText(selectedText);
const tooltip = document.getElementById('tooltip-rightmenu-return');
tooltip.textContent = '选中文本已复制到剪贴板';
tooltip.classList.add('show-tooltip');
setTimeout(() => {
tooltip.classList.remove('show-tooltip');
}, 1500);
}
}
// 必应搜索-在Bing上搜索选中文本功能
function searchSelectedTextBing() {
const selectedText = window.getSelection().toString().trim();
if (selectedText) {
const bingSearchUrl = `https://www.bing.com/search?q=${encodeURIComponent(selectedText)}`;
window.open(bingSearchUrl, '_blank');
}
}
// 下载图片-下载选中图片功能
function downloadImage(imgsrc) {
if (!imgsrc) {
console.error('Image source is required');
return;
}
const name = imgsrc.split('/').pop(); // Extract the image name from the path
fetch(imgsrc)
.then(response => response.blob())
.then(blob => {
const a = document.createElement('a');
const url = URL.createObjectURL(blob);
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(url);
document.body.removeChild(a);
const tooltip = document.getElementById('tooltip-rightmenu-return');
tooltip.textContent = '图片已下载';
tooltip.classList.add('show-tooltip');
setTimeout(() => {
tooltip.classList.remove('show-tooltip');
}, 1500);
})
.catch(error => console.error('Error downloading image:', error));
}
// 复制图片链接-复制选中图片链接功能
function copyImageLink(imgsrc) {
if (imgsrc) {
navigator.clipboard.writeText(imgsrc);
const tooltip = document.getElementById('tooltip-rightmenu-return');
tooltip.textContent = '链接已复制到剪贴板';
tooltip.classList.add('show-tooltip');
setTimeout(() => {
tooltip.classList.remove('show-tooltip');
}, 1500);
}
}
// 随便看看-随机跳转到文章
function RandomGo() {
var posts = JSON.parse(sessionStorage.getItem('posts')) || [];
if (posts.length === 0) {
fetch('/sitemap.xml')
.then(response => response.text())
.then(str => (new window.DOMParser()).parseFromString(str, "text/xml"))
.then(data => {
const entries = data.querySelectorAll('url > loc');
posts = Array.from(entries)
.map(entry => entry.textContent)
.filter(link => link.includes('/_posts/'))
.map(link => link.substring(link.indexOf('/_posts/')));
sessionStorage.setItem('posts', JSON.stringify(posts)); // 保存到 sessionStorage
console.log('Posts updated:', posts); // 调试输出更新后的链接列表
const randomIndex = Math.floor(Math.random() * posts.length);
const randomLink = posts[randomIndex];
window.location.href = randomLink;
})
.catch(error => console.error('Error fetching sitemap:', error));
} else {
const randomIndex = Math.floor(Math.random() * posts.length);
const randomLink = posts[randomIndex];
window.location.href = randomLink;
}
}
// 复制链接-复制当前地址功能
function copyLink() {
const link = window.location.href;
navigator.clipboard.writeText(link);
const tooltip = document.getElementById('tooltip-rightmenu-return');
tooltip.textContent = '链接已复制到剪贴板';
tooltip.classList.add('show-tooltip');
// 3秒后隐藏提示框
setTimeout(() => {
tooltip.classList.remove('show-tooltip');
}, 1500);
}
// 切换昼夜模式功能
function toggleColorMode() {
document.getElementById('color-toggle-btn').click();
if (document.documentElement.getAttribute('data-user-color-scheme') === 'dark' ||
(document.documentElement.getAttribute('data-user-color-scheme') === 'auto' &&
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.getElementById('toggle-color-mode-icon').className = "iconfont icon-dark";
}
else {
document.getElementById('toggle-color-mode-icon').className = "iconfont icon-light";
}
}
// 切换全屏背景功能
function toggleBackgroundMode() {
const BackgroundMode = localStorage.getItem('BackgroundMode');
if (BackgroundMode === 'false' || !BackgroundMode) {
document.querySelector('#web_bg').style.backgroundImage = `${document.querySelector('.banner').style.background.split(' ')[0]}`;
document.querySelector("#banner").style.background = 'url()';
document.querySelector("#banner .mask").style.backgroundColor = 'rgba(0,0,0,0)';
document.getElementById('toggle-background-mode-icon').className = "fa-solid fa-toggle-on";
['#toc', '.category-list'].forEach(selector => {
if (document.querySelector(selector)) {
document.querySelector(selector).style.backgroundColor = "var(--board-bg-color)";
}
});
localStorage.setItem('BackgroundMode', 'true');
}
else {
document.querySelector("#banner").style.background = document.querySelector('#web_bg').style.backgroundImage + " center center / cover no-repeat";
document.querySelector('#web_bg').style.backgroundImage = 'url()';
document.querySelector("#banner .mask").style.backgroundColor = 'rgba(0,0,0,0.3)';
document.getElementById('toggle-background-mode-icon').className = "fa-solid fa-toggle-off";
['#toc', '.category-list'].forEach(selector => {
if (document.querySelector(selector)) {
document.querySelector(selector).style.removeProperty('background-color');
}
});
localStorage.setItem('BackgroundMode', 'false');
}
}
// 初始化图标状态
if (localStorage.getItem('DarkNightMode') === 'true') {
document.getElementById("toggle-color-mode-icon").className = "iconfont icon-light";
} else {
document.getElementById("toggle-color-mode-icon").className = "iconfont icon-dark";
}
if (localStorage.getItem('BackgroundMode') === 'true') {
document.getElementById('toggle-background-mode-icon').className = "fa-solid fa-toggle-on";
} else {
document.getElementById('toggle-background-mode-icon').className = "fa-solid fa-toggle-off";
}这段代码实现了右键菜单的各项功能,包括复制选中文本、必应搜索、跳转到链接、下载图片、复制图片链接、随机跳转到文章以及复制当前页面链接。
总结
通过以上步骤,我们成功实现了一个无侵入式的自定义右键菜单。这个右键菜单不仅美观,而且功能丰富,能够满足大部分用户的需求。以下是完整的使用方法:
- 在 Hexo 的
source/html目录下创建RightMenu.html文件,并将上述HTML结构复制到该文件中。 - 在 Hexo 的
scripts/injector.js文件中添加上述注入器代码。 - 在 Hexo 的
source/css目录下创建RightMenu.css文件,并将上述CSS样式复制到该文件中。 - 在 Hexo 的
source/js目录下创建RightMenu.js文件,并将上述JavaScript代码复制到该文件中,注意需要包括右键菜单显示和隐藏和各项功能实现两部分代码,必要时需要替换RandomGo()函数的实现。
如果你想要使用这个右键菜单,只需将上述代码复制到你的 Hexo 博客中即可。你可以根据自己的需求进一步修改和扩展这个右键菜单的功能。如果你对这个右键菜单有任何疑问或建议,欢迎在评论区留言讨论。