0xarch

I could be myself out there. Bullying, reckless, totally selfish. Doing the things that makes me me. If you ain't who you are, then who the fuck are you?

JavaScript

参数

markdown_content: 文章容器(Node)

需要更改的地方

#toc: 挂载目录的容器

Code

function TOC(markdown_content) {
    let toc = document.querySelector("#toc");
    if(!toc) return;
    let tocList = markdown_content.querySelectorAll("h1, h2, h3, h4, h5, h6");
    let liList = [];
    tocList.forEach((v) => {
        let pid = '_' + Date.now().toString(36) + Math.random().toString(36).replace(/[\s\S]{3}/, '');
        v.id = pid;
        const H = v.nodeName[1];
        let li = document.createElement('li');
        li.classList.add(`li-${H}`);
        li.setAttribute('pid', pid);
        li.textContent = v.textContent;
        li.addEventListener("click", () => {
            window.scrollBy({ top: v.getBoundingClientRect().y, behavior: "smooth" });
        });
        toc.appendChild(li);
        liList.push(li);
    })
    let tocArr = Array.from(tocList);
    const removeClass = () => {
        liList.forEach(v => v.classList.remove("active"));
    }
    const update = () => {
        for (let i = 0; i < tocArr.length; i++) {
            let v = tocArr[i];
            let rect = v.getBoundingClientRect();
            let top = rect.top + rect.height;
            if (top > 0) {
                removeClass();
                let li = liList[i];
                li.classList.add('active');
                /*
                这两句代码用来实现目录左侧的进度条,需要搭配CSS实现,删除没有影响。
                CSS见下文
                toc.style.setProperty('--g-start',li.offsetTop+li.getBoundingClientRect().height-5+'px');
                toc.style.setProperty('--g-end',li.offsetTop+li.getBoundingClientRect().height+5+'px');
                */
                break;
            }
        }
    }
    let ticking = false;
    window.addEventListener("scroll", () => {
        if (!ticking) {
            window.requestAnimationFrame(() => {
                update();
                ticking = false;
            })
        }
        ticking = true;
    });
    update();
}

CSS

需要更改的地方

--brand-color: 高亮颜色 --radius: 圆角

Code

#toc{
    margin: 0;
    list-style: none;
    padding: 0.75rem;
    border-radius: 0.75rem;
    border: 1px solid transparent;
}
#toc::before{
    position: absolute;
    top: 0;
    left: 0;
    width: .1rem;
    height: 100%;
    content: '';
    background: linear-gradient(var(--brand-color) var(--g-start),transparent var(--g-end));
}
#toc>li{
    cursor: pointer;
    padding: 0.125rem 0.25rem;
    border-radius: var(--radius);
    transition: color .2s ease-in-out,background .2s ease-in-out;
}
#toc>.li-1{
    font-size: larger;
}
#toc>.li-2{
    font-size: large;
    padding-left: 0.65rem;
}
#toc>.li-3{
    padding-left: 1.25rem;
}
#toc>li:hover{
    background: var(--brand-color-75);
    color: #fff;
}
#toc>li.active{
    color: var(--brand-color);
}
#toc>li.active:hover{
    background-color: var(--brand-color-25);
}
WebJS - 滚动目录实现
作者0xarch
发布于2024-03-04
许可协议CC BY-ND-SA