<script> $(function () { //当box容器加入到html文档中作为节点 $("body").prepend(` <div id="title_box"> <div id="content" > </div> </div> `) //var arr = ["h1","h2","h3","h4","h5","h6"] var test_box = $("#cnblogs_post_body"); //文章容器 var test_box_childs = test_box.children(); //文章的子节点 var pick_title_node = [] //有效的title节点 //每个小盒子的长度 var box_height = 30 //mbox容器box的高度 var bbb = "#9c9c9c" //最外层容器的背景颜色 var mbox_width = $(window).width()/6 //mbox的宽度 var mbox_margin_size = 2.5 //margin的外边距大小 var active_color = "#0681ba" //mbox活跃时的背景颜色 var mbox_color = "rgba(85, 85, 85,0.9)" //mbox中的背景颜色 var color = "#ebebeb" //mbox中的文字颜色 var current_index = 0 //现在的mbox_index或当前的标题对应的index var listen_scroll = true //是否处理滚动条事件 var tops_size = [] //各个标题距顶部的高度 //选择出标题有效元素节点 for (i = 0; i < test_box_childs.length; i++) { unit_node = test_box_childs[i]; if (unit_node.localName.indexOf("h1") == 0 || unit_node.localName.indexOf("h2") == 0 || unit_node.localName.indexOf("h3") == 0) { pick_title_node[pick_title_node.length] = unit_node } } //将元素节点进行加工成mbox html且追加到页面中作为节点 & 将同将title距顶部的高度加到容器中 for (i = 0; i < pick_title_node.length; i++) { title_str = pick_title_node[i].innerText.trim() $("#content").append("<div id='title_index_" + i + "' title='" + title_str + "'>" + title_str + "</div>") tops_size[tops_size.length] = $(pick_title_node[i]).offset().top } //设置整体盒子样式 if (pick_title_node.length > 0) { $("#title_box").css({ "position": "fixed", "left": "0px", "right": "0px", "top": "0px", "font-size": "10px", "background": bbb, "overflow": "hidden", "z-index": "10000", "border-bottom": "1.5px solid #f5f5f5" }) $("#content").css({ "height": box_height + "px", "overflow": "hidden", "width": mbox_width * pick_title_node.length + mbox_margin_size * 2 * pick_title_node.length + 250 + "px", "position": "relative" }) $("#content").children().css({ "float": "left", "width": mbox_width + "px", "height": "25px", "line-height": "25px", "background": mbox_color, "margin": mbox_margin_size + "px", "padding": "0px 5px", "box-sizing": " border-box", "overflow": "hidden", "text-overflow":"ellipsis", "white-space": "nowrap", "cursor": "pointer", "color": color, "font-weight": "700" }) } //防抖函数模板 function debounce(func, delay) { let timer = null; return function (...args) { if (timer) clearTimeout(timer) timer = setTimeout(() => { func.apply(this, args) }, delay) } } //定位指示灯 //判断mbox的left是否超出,如果超时调整位置 function toLamp() { //执行体 console.log("指针灯排校准中~"); mbox_position_left = $("#title_index_" + current_index).position().left window_width = $(window).width(); if (mbox_position_left + mbox_width > window_width) { $("#content").animate({ "left": (-mbox_width * (current_index - 1)) + "px" }) } else { $("#content").animate({ "left": "0px" }) } } //创建刷新指示灯的防抖函数 const refresh = debounce(toLamp, 120) //当点击mbox时进行事件委托 $("#content").on("click", "div", function () { //点击的index index = parseInt($(this).prop("id").split("_")[2]) //text中真实的obj node = pick_title_node[index] //所在位置 mbox_top = $(node).offset().top //定位到该元素的位置 $(window).scrollTop(mbox_top - box_height); //维护指示灯 $("#title_index_" + index).css({ "background": active_color }).siblings().css({ "background": mbox_color }) //调整活跃的mbox到可视位置1 refresh() //维护index current_index = index }); //监听窗口滑动 $(window).scroll(function () { //查看是否要监听scroll if (listen_scroll) { //维护tile高度容器 for (h = 0; h < pick_title_node.length; h++) { tops_size[h] = $(pick_title_node[h]).offset().top } //当前可视窗口距顶部的位置 t1 = this.scrollY for (j = 0; j < tops_size.length; j++) { //判断在哪个title内 if (tops_size[j] > (t1 + 50)) { //t1+h是为了校准,跟我们加了上面的指示灯有关 index = (j - 1) < 0 ? 0 : j - 1 $("#title_index_" + index).css({ "background": active_color }).siblings().css({ "background": mbox_color }) current_index = j break } else if (t1 > tops_size[tops_size.length - 1]) { //当在最后一个时 $("#title_index_" + (tops_size.length - 1)).css({ "background": active_color }).siblings().css({ "background": mbox_color }) current_index = j break } } //调整活跃的mbox到可视位置2 refresh() } }) }) </script>