Deslizador de línea de tiempo adaptable con JavaScript y CSS

Tiempo de ejecución: 30 minutos. Empezar

Autor: tutsplus
Views Total: 3,110
Sitio oficial: Ir a la web
Actualizado: May 14, 2017
Licencia: MIT

Vista prévia

Deslizador de línea de tiempo adaptable con JavaScript y CSS

Descripción

Una línea de tiempo horizontal, táctil y adaptable que permite deslizar manualmente los eventos al igual que un deslizador.

Funcionamiento

Añada eventos personalizados, marcas de tiempo y flechas de navegación a la línea de tiempos siguiendo la estructura HTML como esta:

<section class="timeline">

<ol>


<li>



<div>




<time>1934</time> At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium



</div>


</li>


<li>



<div>




<time>1937</time> Proin quam velit, efficitur vel neque vitae, rhoncus commodo mi. Suspendisse finibus mauris et bibendum molestie. Aenean ex augue, varius et pulvinar in, pretium non nisi.



</div>


</li>


<li>



<div>




<time>1940</time> Proin iaculis, nibh eget efficitur varius, libero tellus porta dolor, at pulvinar tortor ex eget ligula. Integer eu dapibus arcu, sit amet sollicitudin eros.



</div>


</li>


<li>



<div>




<time>1943</time> In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.



</div>


</li>


<li>



<div>




<time>1946</time> In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.



</div>


</li>


<li>



<div>




<time>1956</time> In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.



</div>


</li>


<li>



<div>




<time>1957</time> In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.



</div>


</li>


<li>



<div>




<time>1967</time> Aenean condimentum odio a bibendum rhoncus. Ut mauris felis, volutpat eget porta faucibus, euismod quis ante.



</div>


</li>


<li>



<div>




<time>1977</time> Vestibulum porttitor lorem sed pharetra dignissim. Nulla maximus, dui a tristique iaculis, quam dolor convallis enim, non dignissim ligula ipsum a turpis.



</div>


</li>


<li>



<div>




<time>1985</time> In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.



</div>


</li>


<li>



<div>




<time>2000</time> In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.



</div>


</li>


<li>



<div>




<time>2005</time> In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.



</div>


</li>


<li></li>

</ol>



<div class="arrows">


<button class="arrow arrow__prev disabled" disabled>



<img src="arrow_prev.svg" alt="prev timeline arrow">


</button>


<button class="arrow arrow__next">



<img src="arrow_next.svg" alt="next timeline arrow">


</button>

</div>
</section>

El CSS básico para la línea de tiempo horizontal.

.timeline {

white-space: nowrap;

overflow-x: hidden;
}

.timeline ol {

font-size: 0;

width: 100vw;

padding: 250px 0;

transition: all 1s;
}

.timeline ol li {

position: relative;

display: inline-block;

list-style-type: none;

width: 160px;

height: 3px;

background: #fff;
}

.timeline ol li:last-child { width: 280px; }

.timeline ol li:not(:first-child) { margin-left: 14px; }

.timeline ol li:not(:last-child)::after {

content: '';

position: absolute;

top: 50%;

left: calc(100% + 1px);

bottom: 0;

width: 12px;

height: 12px;

transform: translateY(-50%);

border-radius: 50%;

background: #F45B69;
}

.timeline ol li div {

position: absolute;

left: calc(100% + 7px);

width: 280px;

padding: 15px;

font-size: 1rem;

white-space: normal;

color: black;

background: white;
}

.timeline ol li div::before {

content: '';

position: absolute;

top: 100%;

left: 0;

width: 0;

height: 0;

border-style: solid;
}

.timeline ol li:nth-child(odd) div {

top: -16px;

transform: translateY(-100%);
}

.timeline ol li:nth-child(odd) div::before {

top: 100%;

border-width: 8px 8px 0 0;

border-color: white transparent transparent transparent;
}

.timeline ol li:nth-child(even) div { top: calc(100% + 16px); }

.timeline ol li:nth-child(even) div::before {

top: -8px;

border-width: 8px 0 0 8px;

border-color: transparent transparent transparent white;
}

.timeline time {

display: block;

font-size: 1.2rem;

font-weight: bold;

margin-bottom: 8px;
}

Estilo de las flechas de línea de tiempo:

.timeline .arrows {

display: flex;

justify-content: center;

margin-bottom: 20px;
}

.timeline .arrows .arrow__prev { margin-right: 20px; }

.timeline .disabled { opacity: .5; }

.timeline .arrows img {

width: 45px;

height: 45px;
}

Haga que la línea de tiempo sea totalmente adaptable.

@media screen and (max-width: 599px) {

.timeline ol,
.timeline ol li { width: auto; }

.timeline ol {

padding: 0;

transform: none !important;
}

.timeline ol li {

display: block;

height: auto;

background: transparent;
}

.timeline ol li:first-child { margin-top: 25px; }

.timeline ol li:not(:first-child) { margin-left: auto; }

.timeline ol li div {

width: 94%;

height: auto !important;

margin: 0 auto 25px;
}

.timeline ol li div { position: static; }

.timeline ol li:nth-child(odd) div { transform: none; }

.timeline ol li:nth-child(odd) div::before,
.timeline ol li:nth-child(even) div::before {

left: 50%;

top: 100%;

transform: translateX(-50%);

border: none;

border-left: 1px solid white;

height: 25px;
}

.timeline ol li:last-child,
.timeline ol li:nth-last-child(2) div::before,
.timeline ol li:not(:last-child)::after,
.timeline .arrows { display: none; }
}

El principal JavaScript para activar la línea de tiempo horizontal.

(function() {


// VARIABLES

const timeline = document.querySelector(".timeline ol"),


elH = document.querySelectorAll(".timeline li > div"),


arrows = document.querySelectorAll(".timeline .arrows .arrow"),


arrowPrev = document.querySelector(".timeline .arrows .arrow__prev"),


arrowNext = document.querySelector(".timeline .arrows .arrow__next"),


firstItem = document.querySelector(".timeline li:first-child"),


lastItem = document.querySelector(".timeline li:last-child"),


xScrolling = 280,


disabledClass = "disabled";


// START

window.addEventListener("load", init);


function init() {


setEqualHeights(elH);


animateTl(xScrolling, arrows, timeline);


setSwipeFn(timeline, arrowPrev, arrowNext);


setKeyboardFn(arrowPrev, arrowNext);

}


// SET EQUAL HEIGHTS

function setEqualHeights(el) {


let counter = 0;


for (let i = 0; i < el.length; i++) {



const singleHeight = el[i].offsetHeight;




if (counter < singleHeight) {




counter = singleHeight;



}


}



for (let i = 0; i < el.length; i++) {



el[i].style.height = `${counter}px`;


}

}


// CHECK IF AN ELEMENT IS IN VIEWPORT

// http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport

function isElementInViewport(el) {


const rect = el.getBoundingClientRect();


return (



rect.top >= 0 &&



rect.left >= 0 &&



rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&



rect.right <= (window.innerWidth || document.documentElement.clientWidth)


);

}


// SET STATE OF PREV/NEXT ARROWS

function setBtnState(el, flag = true) {


if (flag) {



el.classList.add(disabledClass);


} else {



if (el.classList.contains(disabledClass)) {




el.classList.remove(disabledClass);



}



el.disabled = false;


}

}


// ANIMATE TIMELINE

function animateTl(scrolling, el, tl) {


let counter = 0;


for (let i = 0; i < el.length; i++) {



el[i].addEventListener("click", function() {




if (!arrowPrev.disabled) {





arrowPrev.disabled = true;




}




if (!arrowNext.disabled) {





arrowNext.disabled = true;




}




const sign = (this.classList.contains("arrow__prev")) ? "" : "-";




if (counter === 0) {





tl.style.transform = `translateX(-${scrolling}px)`;




} else {





const tlStyle = getComputedStyle(tl);





// add more browser prefixes if needed here





const tlTransform = tlStyle.getPropertyValue("-webkit-transform") || tlStyle.getPropertyValue("transform");





const values = parseInt(tlTransform.split(",")[4]) + parseInt(`${sign}${scrolling}`);





tl.style.transform = `translateX(${values}px)`;




}





setTimeout(() => {





isElementInViewport(firstItem) ? setBtnState(arrowPrev) : setBtnState(arrowPrev, false);





isElementInViewport(lastItem) ? setBtnState(arrowNext) : setBtnState(arrowNext, false);




}, 1100);





counter++;



});


}

}


// ADD SWIPE SUPPORT FOR TOUCH DEVICES

function setSwipeFn(tl, prev, next) {


const hammer = new Hammer(tl);


hammer.on("swipeleft", () => next.click());


hammer.on("swiperight", () => prev.click());

}


// ADD BASIC KEYBOARD FUNCTIONALITY

function setKeyboardFn(prev, next) {


document.addEventListener("keydown", (e) => {



if ((e.which === 37) || (e.which === 39)) {




const timelineOfTop = timeline.offsetTop;




const y = window.pageYOffset;




if (timelineOfTop !== y) {





window.scrollTo(0, timelineOfTop);




}




if (e.which === 37) {





prev.click();




} else if (e.which === 39) {





next.click();




}



}


});

}

})();

 

Te puede interesar: