Skip to content

Commit 7f65aa9

Browse files
committed
Fixed TOC content
1 parent 301b078 commit 7f65aa9

8 files changed

Lines changed: 281 additions & 70 deletions

File tree

assets/js/app.bundle.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/js/index.js

Lines changed: 155 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,15 +425,167 @@
425425
}
426426
},
427427

428+
tocScroll: function() {
429+
var toc = document.querySelector( '#toc' );
430+
var tocPath = document.querySelector( '.toc-marker path' );
431+
var tocItems;
432+
433+
// Factor of screen size that the element must cross
434+
// before it's considered visible
435+
var TOP_MARGIN = 0.1,
436+
BOTTOM_MARGIN = 0.2;
437+
438+
var pathLength;
439+
440+
var lastPathStart,
441+
lastPathEnd;
442+
443+
window.addEventListener( 'resize', drawPath, false );
444+
window.addEventListener( 'scroll', sync, false );
445+
446+
drawPath();
447+
448+
function drawPath() {
449+
450+
tocItems = [].slice.call( toc.querySelectorAll( 'li' ) );
451+
452+
// Cache element references and measurements
453+
tocItems = tocItems.map( function( item ) {
454+
var anchor = item.querySelector( 'a' );
455+
var target = document.getElementById( anchor.getAttribute( 'href' ).slice( 1 ) );
456+
457+
return {
458+
listItem: item,
459+
anchor: anchor,
460+
target: target
461+
};
462+
} );
463+
464+
// Remove missing targets
465+
tocItems = tocItems.filter( function( item ) {
466+
return !!item.target;
467+
} );
468+
469+
var path = [];
470+
var pathIndent;
471+
472+
tocItems.forEach( function( item, i ) {
473+
474+
var x = item.anchor.offsetLeft - 5,
475+
y = item.anchor.offsetTop,
476+
height = item.anchor.offsetHeight;
477+
478+
if( i === 0 ) {
479+
path.push( 'M', x, y, 'L', x, y + height );
480+
item.pathStart = 0;
481+
}
482+
else {
483+
// Draw an additional line when there's a change in
484+
// indent levels
485+
if( pathIndent !== x ) path.push( 'L', pathIndent, y );
486+
487+
path.push( 'L', x, y );
488+
489+
// Set the current path so that we can measure it
490+
tocPath.setAttribute( 'd', path.join( ' ' ) );
491+
item.pathStart = tocPath.getTotalLength() || 0;
492+
493+
path.push( 'L', x, y + height );
494+
}
495+
496+
pathIndent = x;
497+
498+
tocPath.setAttribute( 'd', path.join( ' ' ) );
499+
item.pathEnd = tocPath.getTotalLength();
500+
501+
} );
502+
503+
pathLength = tocPath.getTotalLength();
504+
505+
sync();
506+
507+
}
508+
509+
function fixedTOC() {
510+
if ( $('.post-header').outerHeight(true) + 80 > $(window).scrollTop()) {
511+
$('#toc').css('top',$('.post-header').outerHeight(true));
512+
$('#toc').css('position','absolute');
513+
$('#toc').css('left','20px');
514+
//console.log("top absolute | toc offset = ", $('#toc').offset().top, "scrollTop = ",$(window).scrollTop());
515+
} else {
516+
// 把下面三行注释掉,让目录不固定。有些目录很长的文章,需要这样
517+
$('#toc').css('top',0);
518+
$('#toc').css('position','fixed');
519+
$('#toc').css('left','35px');
520+
// console.log("top fixed | toc offset = ", $('#toc').offset().top, "scrollTop = ",$(window).scrollTop());
521+
}
522+
523+
if ($(window).scrollTop() + $(window).height() > $('.post-footer').offset().top) {
524+
$('#toc').css("visibility","hidden");
525+
$('.toc-marker').css("visibility","hidden");
526+
527+
} else {
528+
$('#toc').css("visibility","visible");
529+
$('.toc-marker').css("visibility","visible");
530+
}
531+
532+
}
533+
function sync() {
534+
535+
fixedTOC();
536+
537+
var windowHeight = window.innerHeight;
538+
539+
var pathStart = pathLength,
540+
pathEnd = 0;
541+
542+
var visibleItems = 0;
543+
544+
tocItems.forEach( function( item ) {
545+
546+
var targetBounds = item.target.getBoundingClientRect();
547+
548+
if( targetBounds.bottom > windowHeight * TOP_MARGIN && targetBounds.top < windowHeight * ( 1 - BOTTOM_MARGIN ) ) {
549+
pathStart = Math.min( item.pathStart, pathStart );
550+
pathEnd = Math.max( item.pathEnd, pathEnd );
551+
552+
visibleItems += 1;
553+
554+
item.listItem.classList.add( 'visible' );
555+
}
556+
else {
557+
item.listItem.classList.remove( 'visible' );
558+
}
559+
560+
} );
561+
562+
// Specify the visible path or hide the path altogether
563+
// if there are no visible items
564+
if( visibleItems > 0 && pathStart < pathEnd ) {
565+
if( pathStart !== lastPathStart || pathEnd !== lastPathEnd ) {
566+
tocPath.setAttribute( 'stroke-dashoffset', '1' );
567+
tocPath.setAttribute( 'stroke-dasharray', '1, '+ pathStart +', '+ ( pathEnd - pathStart ) +', ' + pathLength );
568+
tocPath.setAttribute( 'opacity', 1 );
569+
}
570+
}
571+
else {
572+
tocPath.setAttribute( 'opacity', 0 );
573+
}
574+
575+
lastPathStart = pathStart;
576+
lastPathEnd = pathEnd;
577+
578+
}
579+
},
580+
428581
initTOC: function() {
429582
//初始化 toc 插件
430583
$('#toc').initTOC({
431-
selector: "h1, h2, h3, h4, h5, h6",
584+
selector: "h2, h3, h4, h5, h6",
432585
scope: "article",
433586
overwrite: false,
434587
prefix: "toc"
435588
});
436-
$('#toc').css('top',$('.post-header').outerHeight(true));
437589
},
438590

439591
init: function () {
@@ -451,6 +603,7 @@
451603
themeApp.scrollTop();
452604
themeApp.scrollDown();
453605
themeApp.initTOC();
606+
themeApp.tocScroll();
454607
}
455608
};
456609
/*===========================

assets/js/vendor/jquery.toc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
*/
3434
var createList = function ($wrapper, count) {
3535
while (count--) {
36-
$wrapper = $('<ol/>').appendTo($wrapper);
36+
$wrapper = $('<ul/>').appendTo($wrapper);
3737

3838
if (count) {
3939
$wrapper = $('<li/>').appendTo($wrapper);
@@ -92,7 +92,7 @@
9292
var selector = options.selector;
9393
var scope = options.scope;
9494

95-
var $ret = $('<ol/>');
95+
var $ret = $('<ul/>');
9696
var $wrapper = $ret;
9797
var $lastLi = null;
9898

assets/scss/components/_common.scss

Lines changed: 112 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -285,79 +285,134 @@ hr {
285285
}
286286

287287

288-
#toc
289-
{
290-
display: none;
291-
visibility: hidden;
292-
float: right;
293-
width: 20%;
294-
padding: 0 20px 0 0;
295-
position: absolute;
296-
right: 20px;
297-
}
288+
// #toc
289+
// {
290+
// display: none;
291+
// visibility: hidden;
292+
// float: right;
293+
// width: 20%;
294+
// padding: 0 20px 0 0;
295+
// // position: absolute;
296+
// position: fixed;
297+
// right: 20px;
298+
// }
298299

299-
#toc ol
300-
{
301-
margin: 0 0 0 1em;
302-
padding: 0;
300+
// #toc ol
301+
// {
302+
// margin: 0 0 0 1em;
303+
// padding: 0;
303304

304-
list-style: none;
305-
}
305+
// list-style: none;
306+
// }
306307

307-
#toc li
308-
{
309-
position: relative;
308+
// #toc li
309+
// {
310+
// position: relative;
310311

311-
padding: 0;
312-
}
312+
// padding: 0;
313+
// }
313314

314-
#toc li:before
315-
{
316-
position: absolute;
317-
top: .5em;
318-
left: -1em;
315+
// #toc li:before
316+
// {
317+
// position: absolute;
318+
// top: .5em;
319+
// left: -1em;
319320

320-
border: 5px dashed transparent;
321-
border-left: 5px solid #57a3e8;
322-
}
321+
// border: 5px dashed transparent;
322+
// border-left: 5px solid #57a3e8;
323+
// }
323324

324-
#toc li:before
325-
{
326-
overflow: hidden;
325+
// #toc li:before
326+
// {
327+
// overflow: hidden;
327328

328-
width: 0;
329-
height: 0;
329+
// width: 0;
330+
// height: 0;
330331

331-
content: '';
332-
}
332+
// content: '';
333+
// }
333334

334-
#toc a
335-
{
336-
display: block;
337-
overflow: hidden;
335+
// #toc a
336+
// {
337+
// display: block;
338+
// overflow: hidden;
338339

339-
max-height: 2em;
340+
// max-height: 2em;
340341

341-
cursor: pointer;
342-
transition: color .3s;
343-
white-space: nowrap;
344-
text-decoration: none;
345-
text-overflow: ellipsis;
342+
// cursor: pointer;
343+
// transition: color .3s;
344+
// white-space: nowrap;
345+
// text-decoration: none;
346+
// text-overflow: ellipsis;
346347

347-
color: #6aa7c0;
348-
}
348+
// color: #6aa7c0;
349+
// }
350+
351+
// #toc a:hover
352+
// {
353+
// color: #f3a01e;
354+
// }
355+
356+
// #toc h4
357+
// {
358+
// font-size: 18px;
359+
// margin: .75em 0;
360+
// padding-bottom: .25em;
361+
// color: #3b3b3b;
362+
// }
363+
364+
// @media only screen and (min-width: 1570px) {
365+
// #toc {
366+
// visibility: visible;
367+
// display: block;
368+
// }
369+
// }
349370

350-
#toc a:hover
351-
{
352-
color: #f3a01e;
371+
#toc {
372+
padding: 1em;
373+
line-height: 2;
374+
display: none;
375+
visibility: hidden;
376+
width: 20%;
377+
position: fixed;
378+
// float: right;
379+
// right: 20px;
380+
left: 20px;
381+
382+
ul {
383+
list-style: none;
384+
padding: 0;
385+
margin: 0;
386+
}
387+
388+
ul ul {
389+
padding-left: 2em;
390+
}
391+
392+
li a {
393+
display: inline-block;
394+
color: var(--text-body);
395+
text-decoration: none;
396+
transition: all 0.3s cubic-bezier(0.230, 1.000, 0.320, 1.000);
397+
}
398+
399+
li.visible>a {
400+
color: #fda403;
401+
transform: translate( 5px );
402+
}
353403
}
354404

355-
#toc h4
356-
{
357-
font-size: 18px;
358-
margin: .75em 0;
359-
padding-bottom: .25em;
360-
color: #3b3b3b;
405+
.toc-marker {
406+
position: absolute;
407+
top: 0;
408+
left: 0;
409+
width: 100%;
410+
height: 100%;
411+
z-index: -1;
412+
413+
path {
414+
transition: all 0.3s ease;
415+
}
361416
}
362417

363418
@media only screen and (min-width: 1570px) {

0 commit comments

Comments
 (0)