MenuTree 是一个嵌入式文章内容目录树插件,可使用短代码标签或模板函数自定显示位置。目前,在 Typecho-Fans 插件目录中有收集,我使用的是 v0.1.2 社区维护版,其他版本没有去尝试了。
一、引入插件
参照插件的使用说明操作即可。
- 下载本插件,放在
usr/plugins/
目录中,确保文件夹名为MenuTree
; - 激活插件,设置内可开关“嵌入模式”即文章标签输出,“独立模式”即模板函数输出;
- “嵌入模式”勾选时,编辑文章用按钮插入或手写
< !-- index-menu -->
标签发布即可显示目录树; - “独立模式”勾选时,修改模板文件如 post.php 中写入
<?php $this->treeMenu(); ?>
也可显示。
我是使用的“独立模式”,在模板文件中写入 <?php $this->treeMenu(); ?>
来实现的。
二、样式修改
插件仅输出 html 不带 css,需根据以下 class 命名自行处理样式:
.index-menu 容器 div
.index-menu-list 列表 ul
.index-menu-item 列表项 li
.index-menu-link 列表项链接 a
.menu-target-fix {display:block; position:relative; top:-60px; //偏移量} //锚点跳转定位
这个比较好设置,比如,我目前使用的是 tailwindcss ,在主 css 文件中插入的代码是这样的:
/* MenuTree插件需要的样式 */
/* 目录容器 */
.index-menu {
@apply flex-1;
@apply flex;
@apply flex-col;
@apply w-full;
@apply -ml-2;
}
/* 列表 ul */
.index-menu .index-menu-list {
@apply flex-1;
@apply flex;
@apply flex-col;
@apply ml-2;
@apply my-1;
}
/* 列表项 li */
.index-menu .index-menu-item {
@apply flex-1;
@apply flex;
@apply flex-col;
@apply ml-2;
@apply my-1;
@apply overflow-hidden;
}
/* 列表项链接 a */
.index-menu .index-menu-link {
@apply flex-1;
@apply flex;
@apply mx-auto;
@apply w-full;
@apply hover:text-blue-400;
@apply hover:bg-slate-200;
@apply dark:hover:bg-slate-600;
@apply line-clamp-1;
}
/* 当前锚点 */
.index-menu .current {
@apply bg-slate-200;
@apply dark:bg-slate-600;
}
三、给目录加上高亮/动态跟踪目录效果
因为水平有限,这个功能网上找资料搞了半天,终于解决了,代码不多。在js 文件中插入下面代码:
// ------ MenuTree 插件文章目录树动态高亮-----//
//参考:https://blog.csdn.net/qq_43684588/article/details/125048254
// 滚动监听,找到锚点后,将对应的文章目录增加一个 current 的类
document.addEventListener("scroll", function () {
const sections = document.querySelectorAll(".menu-target-fix"); //
const scroll = document.documentElement.scrollTop || document.body.scrollTop;
for (let i = sections.length - 1; i >= 0; i--) {
if (parseInt(scroll) >= Math.ceil(sections[i].offsetTop) - 10) {
activeLoadScroll(i);
return
}
}
});
// 增加current 类的函数,参数为文章所有锚点的索引值
function activeLoadScroll(indexid) {
const i = indexid;
const categoryDomA = document.querySelectorAll("#tocbox .index-menu a");
for (let j = 0; j <= categoryDomA.length - 1; j++) {
if (j == i) {
categoryDomA[j].classList.add("current");
} else {
categoryDomA[j].classList.remove("current");
}
}
}
效果正如本文右侧的目录树。