Cara animada TDC Nav para contenido web largo
| Autor: | hakimel |
|---|---|
| Views Total: | 1,743 |
| Sitio oficial: | Ir a la web |
| Actualizado: | January 13, 2017 |
| Licencia: | MIT |
Vista prévia
Descripción
Se trata de un TOC lateral bastante Cool (tabla de contenido) & sistema de navegación que permite resaltar el elemento NAV actual con una línea animada de progreso cuando se desplaza a través de la Página Web.
Funcionamiento
Cree la TDC & navegación junto con las secciones de contenido correspondientes y la barra de progreso basada en SVG en la Página Web de la siguiente manera:
<nav class="toc"> <ul> <li><a href="#section1">Section One</a></li> <li> <a href="#section2">Section Two</a> <ul> <li><a href="#section21">Section 2-1</a></li> <li><a href="#section22">Section 2-2</a></li> <li><a href="#section23">Section 2-3</a></li> </ul> </li> </ul> <svg class="toc-marker" width="200" height="200" xmlns="http://www.w3.org/2000/svg"> <path stroke="#444" stroke-width="3" fill="transparent" stroke-dasharray="0, 0, 0, 1000" stroke-linecap="round" stroke-linejoin="round" transform="translate(-0.5, -0.5)" /> </svg> </nav>
<article class="contents"> <section id="section1"> <h2>Section One</h2> </section> <section> <div id="section2"> <h2>Section Two</h2> </div> <div id="section21"> <h3>Section 2-1</h3> </div> <div id="section22"> <h3>Section 2-2</h3> </div> </section> ...... </article>
Estilo de la TDC & navegación.
.toc {
position: fixed;
left: 3em;
top: 5em;
padding: 1em;
width: 14em;
line-height: 2;
}
.toc ul {
list-style: none;
padding: 0;
margin: 0;
}
.toc ul ul { padding-left: 2em; }
.toc li a {
display: inline-block;
color: #aaa;
text-decoration: none;
-webkit-transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
}
.toc li.visible > a {
color: #111;
-webkit-transform: translate(5px);
transform: translate(5px);
}
.toc-marker {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.toc-marker path {
-webkit-transition: all 0.3s ease;
transition: all 0.3s ease;
} El principal JavaScript:
var toc = document.querySelector( '.toc' );
var tocPath = document.querySelector( '.toc-marker path' );
var tocItems;
// Factor of screen size that the element must cross
// before it's considered visible
var TOP_MARGIN = 0.1,
BOTTOM_MARGIN = 0.2;
var pathLength;
window.addEventListener( 'resize', drawPath, false );
window.addEventListener( 'scroll', sync, false );
drawPath();
function drawPath() {
tocItems = [].slice.call( toc.querySelectorAll( 'li' ) );
// Cache element references and measurements
tocItems = tocItems.map( function( item ) {
var anchor = item.querySelector( 'a' );
var target = document.getElementById( anchor.getAttribute( 'href' ).slice( 1 ) );
return {
listItem: item,
anchor: anchor,
target: target
};
} );
// Remove missing targets
tocItems = tocItems.filter( function( item ) {
return !!item.target;
} );
var path = [];
var pathIndent;
tocItems.forEach( function( item, i ) {
var x = item.anchor.offsetLeft - 5,
y = item.anchor.offsetTop,
height = item.anchor.offsetHeight;
if( i === 0 ) {
path.push( 'M', x, y, 'L', x, y + height );
item.pathStart = tocPath.getTotalLength() || 0;
}
else {
// Draw an additional line when there's a change in
// indent levels
if( pathIndent !== x ) path.push( 'L', pathIndent, y );
path.push( 'L', x, y );
// Set the current path so that we can measure it
tocPath.setAttribute( 'd', path.join( ' ' ) );
item.pathStart = tocPath.getTotalLength() || 0;
path.push( 'L', x, y + height );
}
pathIndent = x;
tocPath.setAttribute( 'd', path.join( ' ' ) );
item.pathEnd = tocPath.getTotalLength();
} );
pathLength = tocPath.getTotalLength();
sync();
}
function sync() {
var windowHeight = window.innerHeight;
var pathStart = Number.MAX_VALUE,
pathEnd = 0;
var visibleItems = 0;
tocItems.forEach( function( item ) {
var targetBounds = item.target.getBoundingClientRect();
if( targetBounds.bottom > windowHeight * TOP_MARGIN && targetBounds.top < windowHeight * ( 1 - BOTTOM_MARGIN ) ) {
pathStart = Math.min( item.pathStart, pathStart );
pathEnd = Math.max( item.pathEnd, pathEnd );
visibleItems += 1;
item.listItem.classList.add( 'visible' );
}
else {
item.listItem.classList.remove( 'visible' );
}
} );
// Specify the visible path or hide the path altogether
// if there are no visible items
if( visibleItems > 0 && pathStart < pathEnd ) {
tocPath.setAttribute( 'stroke-dashoffset', '1' );
tocPath.setAttribute( 'stroke-dasharray', '1, '+ pathStart +', '+ ( pathEnd - pathStart ) +', ' + pathLength );
tocPath.setAttribute( 'opacity', 1 );
}
else {
tocPath.setAttribute( 'opacity', 0 );
}
}





