此文章已过期,请查看新文

写此篇文章时,主题 已内置此功能。
Solitude 主题 twikoowalinevaline 都支持热评功能,目前主题正在积极维护中。

展示

热评

Waline 源码

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
function initializeCommentBarrage() {
window.commentBarrageInitialized = !0;
let config = {
maxBarrage: 1,
barrageTime: 8e3,
walineUrl: "此处填你的waline部署地址",
pageUrl: window.location.pathname,
}
new class {
commentInterval = null

constructor(config) {
this.config = {
...config,
barrageTimer: [],
barrageList: [],
barrageIndex: 0,
dom: document.querySelector(".comment-barrage")
};
this.commentInterval = null;
this.hoverOnCommentBarrage = false;
this.init();
}

async fetchComments() {
const url = new URL(`${this.config.walineUrl}/api/comment`);
const params = {
path: this.config.pageUrl,
sortBy: 'insertedAt_asc'
};

for (const [key, value] of Object.entries(params)) {
url.searchParams.append(key, value);
}

try {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json"
},
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();
return data.data;
} catch (error) {
console.error("An error occurred while fetching comments: ", error);
}
}

commentLinkFilter(comments) {
return comments.data.flatMap(comment => this.getCommentReplies(comment));
}

getCommentReplies(comment) {
if (!comment.replies) {
return [comment];
}
return [comment, ...comment.replies.flatMap(reply => this.getCommentReplies(reply))];
}

processCommentContent(comment) {
const processed = comment.replace(/<blockquote\b[^>]*>[\s\S]*?<\/blockquote>|<[^>]*>|\n/g, "").trim();
return processed ? `<p>${processed}</p>` : "";
}

createCommentBarrage(comment) {
const content = this.processCommentContent(comment.comment).trim();
if (!content) {
return false;
}

const element = document.createElement("div");
element.classList.add("comment-barrage-item");
element.innerHTML = `
<div class="barrageHead">
<a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">热评</a>
<div class="barrageNick">${comment.nick}</div>
<img class="barrageAvatar" src="https://cravatar.cn/avatar/${comment.avatar}"/>
</div>
<a class="barrageContent" href="javascript:sco.scrollTo('${comment.objectId}');">${comment.comment}</a>
`;

this.config.dom.appendChild(element);
this.config.barrageTimer.push(element);

return true;
}

removeCommentBarrage(element) {
element.className = "comment-barrage-item out";
setTimeout(() => {
this.config.dom.removeChild(element);
}, 1000);
}

async initCommentBarrage() {
const commentBarrage = document.querySelector(".comment-barrage");
const menuCommentBarrageText = document.querySelector(".menu-commentBarrage-text");
const consoleCommentBarrage = document.querySelector("#consoleCommentBarrage");

if (localStorage.getItem("commentBarrageSwitch") != null) {
commentBarrage.style.display = "flex";
consoleCommentBarrage.classList.add("on");
} else {
commentBarrage.style.display = "none";
consoleCommentBarrage.classList.remove("on");
}

const comments = await this.fetchComments();
this.config.barrageList = this.commentLinkFilter(comments);
this.config.dom.innerHTML = "";
clearInterval(this.commentInterval);
this.commentInterval = null;

const createOrRemoveBarrage = () => {
if (this.config.barrageList.length && !this.hoverOnCommentBarrage) {
if (!this.createCommentBarrage(this.config.barrageList[this.config.barrageIndex])) {
this.config.barrageIndex = (this.config.barrageIndex + 1) % this.config.barrageList.length;
return createOrRemoveBarrage();
}
this.config.barrageIndex = (this.config.barrageIndex + 1) % this.config.barrageList.length;
}
if (this.config.barrageTimer.length > (this.config.barrageList.length > this.config.maxBarrage ? this.config.maxBarrage : this.config.barrageList.length) && !this.hoverOnCommentBarrage) {
this.removeCommentBarrage(this.config.barrageTimer.shift());
}
};

setTimeout(() => {
createOrRemoveBarrage();
if (this.commentInterval) {
clearInterval(this.commentInterval);
}
this.commentInterval = setInterval(createOrRemoveBarrage, this.config.barrageTime);
}, 3000);
}

async init() {
await this.initCommentBarrage();
const commentBarrage = document.querySelector(".comment-barrage");
commentBarrage.addEventListener('mouseover', () => this.hoverOnCommentBarrage = true);
commentBarrage.addEventListener('mouseout', () => this.hoverOnCommentBarrage = false);
}
}
(config)
}
initializeCommentBarrage()

如果使用了 Pjax 刷新页面,还需要将 initializeCommentBarrage 添加到 pjax:complete

Valine 源码

检查网站有没有引用 md5 库,如果没有,在适当位置插入:

1
<script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.19.0/js/md5.min.js" referrerpolicy="no-referrer"></script>
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
function initializeCommentBarrage() {
window.commentBarrageInitialized = !0;
let config = {
maxBarrage: 1,
barrageTime: 8e3,
valineUrl: "此处填你的waline部署地址",
pageUrl: window.location.pathname,
}
new class {
commentInterval = null

constructor(config) {
this.config = {
...config,
barrageTimer: [],
barrageList: [],
barrageIndex: 0,
dom: document.querySelector(".comment-barrage")
};
this.commentInterval = null;
this.hoverOnCommentBarrage = false;
this.init();
}

async fetchComments() {
const url = new URL(`${this.config.valineUrl}/1.1/classes/Comment`);
const params = {
url: this.config.pageUrl,
order: '-createdAt'
};

for (const [key, value] of Object.entries(params)) {
url.searchParams.append(key, value);
}

try {
const response = await fetch(url, {
method: "GET",
headers: {
"X-LC-Id": GLOBAL_CONFIG.comment.appId,
"X-LC-Key": GLOBAL_CONFIG.comment.appKey,
"Content-Type": "application/json"
},
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();
return data.results.filter(item => item.url === this.config.pageUrl)
} catch (error) {
console.error("An error occurred while fetching comments: ", error);
}
}

commentLinkFilter(comments) {
return comments.flatMap(comment => this.getCommentReplies(comment));
}

getCommentReplies(comment) {
window.comment = comment
if (!comment.replies) {
return [comment];
}
return [comment, ...comment.replies.flatMap(reply => this.getCommentReplies(reply))];
}

processCommentContent(comment) {
const processed = comment.replace(/```[\s\S]*?```|<blockquote\b[^>]*>[\s\S]*?<\/blockquote>|<[^>]*>|\n|`([^`]{1,9})`:/g, "").trim();
return processed ? `<p>${processed}</p>` : "";
}

createCommentBarrage(comment) {
const content = this.processCommentContent(comment.comment).trim();
if (!content) {
return false;
}

const element = document.createElement("div");
element.classList.add("comment-barrage-item");
element.innerHTML = `
<div class="barrageHead">
<a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">热评</a>
<div class="barrageNick">${comment.nick}</div>
<img class="barrageAvatar" src="https://cravatar.cn/avatar/${md5(comment.mail.toLowerCase())}"/>
</div>
<a class="barrageContent" href="javascript:sco.scrollTo('${comment.objectId}');">${comment.comment}</a>
`;

this.config.dom.appendChild(element);
this.config.barrageTimer.push(element);

return true;
}

removeCommentBarrage(element) {
element.className = "comment-barrage-item out";
setTimeout(() => {
this.config.dom.removeChild(element);
}, 1000);
}

async initCommentBarrage() {
const commentBarrage = document.querySelector(".comment-barrage");
const menuCommentBarrageText = document.querySelector(".menu-commentBarrage-text");
const consoleCommentBarrage = document.querySelector("#consoleCommentBarrage");

if (localStorage.getItem("commentBarrageSwitch") != null) {
commentBarrage.style.display = "flex";
consoleCommentBarrage.classList.add("on");
} else {
commentBarrage.style.display = "none";
consoleCommentBarrage.classList.remove("on");
}

const comments = await this.fetchComments();
this.config.barrageList = this.commentLinkFilter(comments);
this.config.dom.innerHTML = "";
clearInterval(this.commentInterval);
this.commentInterval = null;

const createOrRemoveBarrage = () => {
if (this.config.barrageList.length && !this.hoverOnCommentBarrage) {
if (!this.createCommentBarrage(this.config.barrageList[this.config.barrageIndex])) {
this.config.barrageIndex = (this.config.barrageIndex + 1) % this.config.barrageList.length;
return createOrRemoveBarrage();
}
this.config.barrageIndex = (this.config.barrageIndex + 1) % this.config.barrageList.length;
}
if (this.config.barrageTimer.length > (this.config.barrageList.length > this.config.maxBarrage ? this.config.maxBarrage : this.config.barrageList.length) && !this.hoverOnCommentBarrage) {
this.removeCommentBarrage(this.config.barrageTimer.shift());
}
};

setTimeout(() => {
createOrRemoveBarrage();
if (this.commentInterval) {
clearInterval(this.commentInterval);
}
this.commentInterval = setInterval(createOrRemoveBarrage, this.config.barrageTime);
}, 3000);
}

async init() {
await this.initCommentBarrage();
const commentBarrage = document.querySelector(".comment-barrage");
commentBarrage.addEventListener('mouseover', () => this.hoverOnCommentBarrage = true);
commentBarrage.addEventListener('mouseout', () => this.hoverOnCommentBarrage = false);
}
}
(config)
}

如果使用了 Pjax 刷新页面,还需要将 initializeCommentBarrage 添加到 pjax:complete

使用

搜寻代码中 sco.scrollTo,替换成自己的或者删除。

安知鱼主题还可修改此部分添加关闭按钮(此扩展与安知鱼主题无关,加上修改方法只是方便使用安知鱼主题的站长修改)

1
2
3
4
5
6
7
8
9
10
11
<div class="barrageHead">
- <a class="barrageTitle" href="javascript:sco.scrollTo('post-comment')">热评</a>
+ <a class="barrageTitle" href="javascript:anzhiyu.scrollTo('#post-comment')">热评</a>
<div class="barrageNick">${comment.nick}</div>
<img class="barrageAvatar" src="https://cravatar.cn/avatar/${md5(comment.mail.toLowerCase())}"/>
+ <a class="comment-barrage-close" href="javascript:anzhiyu.switchCommentBarrage()">
+ <i class="anzhiyufont anzhiyu-icon-xmark"></i>
+ </a>
</div>
- <a class="barrageContent" href="">${comment.comment}</a>
+ <a class="barrageContent" href="javascript:anzhiyu.scrollTo('${comment.objectId}');">${comment.comment}</a>

样式源码

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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
:root {
--efu-white: #fff;
--efu-white-op: rgba(255, 255, 255, 0.2);
--efu-black: #000;
--efu-black-op: rgba(0, 0, 0, 0.2);
--efu-none: rgba(0, 0, 0, 0);
--efu-gray: #999;
--efu-gray-op: rgba(153, 153, 153, 0.169);
--efu-cyan: #00bcd4;
--efu-cyan-op: rgba(0, 188, 212, 0.169);
--efu-vip: #e5a80d;
--efu-speed: #57bd6a;
--efu-main: var(--efu-theme);
--efu-main-op: var(--efu-theme-op);
--efu-main-op-deep: var(--efu-theme-op-deep);
--efu-main-op-light: var(--efu-theme-op-light);
--efu-main-none: var(--efu-theme-none);
--efu-shadow-theme: 0 8px 12px -3px var(--efu-theme-op);
--efu-shadow-blackdeep: 0 2px 16px -3px rgba(0, 0, 0, 0.15);
--efu-shadow-main: 0 8px 12px -3px var(--efu-main-op);
--efu-shadow-blue: 0 8px 12px -3px rgba(40, 109, 234, 0.2);
--efu-shadow-white: 0 8px 12px -3px rgba(255, 255, 255, 0.2);
--efu-shadow-black: 0 0 12px 4px rgba(0, 0, 0, 0.05);
--efu-shadow-yellow: 0px 38px 77px -26px rgba(255, 201, 62, 0.12);
--efu-shadow-red: 0 8px 12px -3px rgba(238, 125, 121, 0.212);
--efu-shadow-green: 0 8px 12px -3px rgba(135, 238, 121, 0.212);
--efu-logo-color: linear-gradient(215deg, #4584ff 0%, #cf0db9 100%);
--efu-snackbar-time: 5s;
--global-font-size: 14px;
--global-bg: #fff;
--hr-border: #97bcfb;
--hr-before-color: #6ea2f9;
--search-bg: #f6f8fa;
--search-input-color: #4c4948;
--search-result-title: #4c4948;
--preloader-bg: #37474f;
--preloader-color: #fff;
--tab-border-color: #f0f0f0;
--tab-botton-bg: #f0f0f0;
--tab-botton-color: #1f2d3d;
--tab-button-hover-bg: #dcdcdc;
--tab-button-active-bg: #fff;
--sidebar-bg: #f6f8fa;
--btn-hover-color: #ff7242;
--btn-color: #fff;
--btn-bg: #307af6;
--text-bg-hover: #307af6;
--light-grey: #eee;
--text-highlight-color: #1f2d3d;
--blockquote-color: #6a737d;
--blockquote-bg: rgba(73, 177, 245, 0.1);
--reward-pop: #f5f5f5;
--toc-link-color: #666261;
--card-box-shadow: 0 3px 8px 6px rgba(7, 17, 27, 0.06);
--card-hover-box-shadow: 0 3px 8px 6px rgba(7, 17, 27, 0.15);
--offset: 0px;
--hlscrollbar-bg: #121212;
}

[data-theme=dark] {
--efu-theme: #5bc167;
--efu-theme-op: rgba(91, 193, 103, 0.137);
--efu-theme-op-deep: rgba(91, 193, 103, 0.867);
--efu-theme-none: '#5BC16700';
--efu-blue: #0084ff;
--efu-red: #ff3842;
--efu-pink: #d44040;
--efu-green: #3e9f50;
--efu-purple: #7a60d2;
--efu-yellow: #ffc93e;
--efu-yellow-op: rgba(255, 201, 62, 0.188);
--efu-orange: #ff953e;
--efu-fontcolor: #f7f7fa;
--efu-background: #18171d;
--efu-reverse: #fff;
--efu-maskbg: rgba(0, 0, 0, 0.6);
--efu-maskbgdeep: rgba(0, 0, 0, 0.85);
--efu-hovertext: #0a84ff;
--efu-ahoverbg: #fff;
--efu-lighttext: var(--efu-theme);
--efu-secondtext: #a1a2b8;
--efu-scrollbar: rgba(200, 200, 223, 0.4);
--efu-card-btn-bg: #30343f;
--efu-post-blockquote-bg: #000;
--efu-post-tabs-bg: #121212;
--efu-secondbg: #30343f;
--efu-shadow-nav: 0 5px 20px 0px rgba(28, 28, 28, 0.4);
--efu-card-bg: #1b1c20;
--efu-card-bg-op: var(--efu-white-op);
--efu-card-bg-none: rgba(29, 27, 38, 0);
--efu-shadow-lightblack: 0 5px 12px -5px rgba(102, 68, 68, 0);
--efu-shadow-light2black: 0 5px 12px -5px rgba(102, 68, 68, 0);
--efu-card-border: #3d3d3f;
--efu-shadow-border: 0 8px 16px -4px rgba(0, 0, 0, 0.314);
--style-border: 1px solid var(--efu-card-border);
--style-border-always: 1px solid var(--efu-card-border);
--style-border-hover: 1px solid var(--efu-theme);
--style-border-hover-always: 1px solid var(--efu-theme);
--style-border-dashed: 1px dashed var(--efu-theme-op);
--style-border-forever: 2px solid var(--efu-lighttext);
--efu-hl-bg: #1c1e1e;
--efu-hltools-bg: #454a50;
}

[data-theme=light] {
--efu-theme: #0e83cd;
--efu-theme-op: rgba(14, 131, 205, 0.137);
--efu-theme-op-deep: rgba(14, 131, 205, 0.867);
--efu-theme-op-light: rgba(66, 89, 239, 0.051);
--efu-theme-none: '#0E83CD00';
--efu-blue: #425aef;
--efu-red: #f04a63;
--efu-pink: #ff7c7c;
--efu-green: #57bd6a;
--efu-yellow: #c28b00;
--efu-yellow-op: rgba(217, 156, 0, 0.102);
--efu-orange: #e38100;
--efu-purple: #7a60d2;
--efu-fontcolor: #363636;
--efu-background: #f7f9fe;
--efu-reverse: #000;
--efu-maskbg: rgba(255, 255, 255, 0.6);
--efu-maskbgdeep: rgba(255, 255, 255, 0.85);
--efu-hovertext: var(--efu-main);
--efu-ahoverbg: #f7f7fa;
--efu-lighttext: var(--efu-main);
--efu-secondtext: rgba(60, 60, 67, 0.8);
--efu-scrollbar: rgba(60, 60, 67, 0.4);
--efu-card-btn-bg: #edf0f7;
--efu-post-blockquote-bg: #fafcff;
--efu-post-tabs-bg: #f2f5f8;
--efu-secondbg: #f7f7f9;
--efu-shadow-nav: 0 5px 12px -5px rgba(102, 68, 68, 0.05);
--efu-card-bg: #fff;
--efu-card-bg-op: var(--efu-black-op);
--efu-card-bg-none: rgba(255, 255, 255, 0);
--efu-shadow-lightblack: 0 5px 12px -5px rgba(102, 68, 68, 0);
--efu-shadow-light2black: 0 5px 12px -5px rgba(102, 68, 68, 0);
--efu-card-border: #e3e8f7;
--efu-shadow-border: 0 8px 16px -4px rgba(44, 45, 48, 0.047);
--style-border: 1px solid var(--efu-card-border);
--style-border-always: 1px solid var(--efu-card-border);
--style-border-hover: 1px solid var(--efu-main);
--style-border-hover-always: 1px solid var(--efu-main);
--style-border-dashed: 1px dashed var(--efu-theme-op);
--style-border-forever: 2px solid var(--efu-main);
--efu-navbg: var(--efu-theme-op);
--efu-hl-bg: #fff;
--efu-hltools-bg: #e7e7e7;
}

.comment-barrage {
position: fixed;
bottom: 0;
right: 20px;
padding: 0 0 20px 10px;
display: flex;
flex-direction: column;
justify-content: flex-end;
z-index: 999;
transition: all 0.3s ease 0s;
user-select: none;
}

@media screen and (max-width: 768px) {
.comment-barrage {
display: none !important;
}
}

.comment-barrage .comment-barrage-item {
min-width: 300px;
max-width: 300px;
width: fit-content;
min-height: 80px;
max-height: 150px;
margin: 4px;
padding: 8px 14px;
background: var(--efu-maskbgdeep);
border-radius: 8px;
color: var(--efu-fontcolor);
animation: 0.6s cubic-bezier(0.42, 0, 0.3, 1.11) 0s 1 normal none running barrageIn;
transition: all 0.3s ease 0s;
display: flex;
flex-direction: column;
border: var(--style-border);
backdrop-filter: saturate(180%) blur(20px);
box-shadow: var(--efu-shadow-border);
overflow: hidden;
}

.comment-barrage .comment-barrage-item:hover {
border: var(--style-border-hover);
box-shadow: var(--efu-shadow-main);
}

.comment-barrage .comment-barrage-item.out {
opacity: 0;
animation: 0.6s cubic-bezier(0.42, 0, 0.3, 1.11) 0s 1 normal none running barrageOut;
}

.comment-barrage .comment-barrage-item.hovered {
opacity: 0;
}

.comment-barrage .comment-barrage-item .comment-barrage-close {
color: var(--efu-secondtext);
cursor: pointer;
line-height: 1;
margin: 4px;
}

.comment-barrage .comment-barrage-item .comment-barrage-close:hover {
color: var(--efu-main);
}

.comment-barrage .comment-barrage-item .comment-barrage-close .solitude {
color: var(--efu-fontcolor);
font-size: 18px;
}

.comment-barrage .comment-barrage-item .barrageHead {
height: 30px;
padding: 0px 0px 6px;
line-height: 30px;
font-size: 12px;
border-bottom: var(--style-border);
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 700;
}

.comment-barrage .comment-barrage-item .barrageHead .barrageTitle {
color: var(--efu-card-bg);
margin-right: 8px;
background: var(--efu-fontcolor);
line-height: 1;
padding: 4px;
border-radius: 4px;
white-space: nowrap;
}

.comment-barrage .comment-barrage-item .barrageHead .barrageTitle:hover {
background: var(--efu-main);
color: var(--efu-white);
}

.comment-barrage .comment-barrage-item .barrageAvatar {
width: 16px;
height: 16px;
margin: 0px 8px 0px auto;
border-radius: 50%;
background: var(--efu-secondbg);
}

.comment-barrage .comment-barrage-item .barrageContent {
height: calc(100% - 30px);
overflow: hidden;
width: fit-content;
max-height: 48px;
font-size: 14px !important;
font-weight: 400 !important;
}

.comment-barrage .comment-barrage-item .barrageContent h1, .comment-barrage .comment-barrage-item .barrageContent h2, .comment-barrage .comment-barrage-item .barrageContent h3, .comment-barrage .comment-barrage-item .barrageContent h4 {
font-size: 14px !important;
font-weight: 400 !important;
margin: 8px 0px !important;
}

.comment-barrage .comment-barrage-item .barrageContent a {
pointer-events: none;
font-size: 14px !important;
}

.comment-barrage .comment-barrage-item .barrageContent p {
margin: 8px 0;
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
font-size: 14px;
max-width: 270px;
}

.comment-barrage .comment-barrage-item .barrageContent p img:not(.tk-owo-emotion), .comment-barrage .comment-barrage-item .barrageContent p display none, .comment-barrage .comment-barrage-item .barrageContent p img.tk-owo-emotion {
width: 16px;
padding: 0;
margin: 0;
transform: translateY(2px);
}

.comment-barrage .comment-barrage-item .barrageContent pre {
display: none;
}

.comment-barrage .comment-barrage-item .barrageContent li {
display: none;
}

.comment-barrage .comment-barrage-item .barrageContent blockquote {
display: none;
}

.comment-barrage .comment-barrage-item .barrageContent br {
display: none;
}

.comment-barrage .comment-barrage-item .barrageContent::-webkit-scrollbar {
height: 0;
width: 4px;
}

.comment-barrage .comment-barrage-item .barrageContent::-webkit-scrollbar-button {
display: none;
}

自行修改样式中的颜色值,然后删除我的。

实现原理

  1. 初始化配置和状态:定义一个配置对象config,包含最大弹幕数、弹幕显示时间间隔、评论服务的 URL 和当前页面的 URL。同时,通过window.commentBarrageInitialized标记弹幕是否已初始化,避免重复初始化。
  2. 弹幕类:定义了一个处理评论弹幕逻辑的类。这个类包含以下关键功能:
    • 评论获取(fetchComments):异步从配置的 Waline 服务地址通过 API 获取当前页面的评论数据。
    • 评论链接和处理(commentLinkFilter, getCommentReplies, processCommentContent):这些方法用于处理从服务获取的评论数据,包括筛选、获取回复以及清理评论文本的 HTML 标签。
    • 创建和移除弹幕(createCommentBarrage, removeCommentBarrage):这些方法用于根据处理后的评论数据创建弹幕元素,并将它们添加到 DOM 中或在一定时间后移除。
    • 初始化弹幕显示逻辑(initCommentBarrage):这个方法设置了一个定时器,定期检查是否应该添加新的弹幕或移除旧的弹幕,并控制弹幕的显示。
    • 鼠标悬停控制:通过监听鼠标悬停事件来暂停或恢复弹幕的移动,避免用户在阅读时被干扰。

支持我的项目

如果对你有所帮助,请对主题进行赞助

Star number