Created
August 17, 2018 00:08
-
-
Save juanmanuelramallo/ab3e6ad35fd26d89aac8a3fb8036afbc to your computer and use it in GitHub Desktop.
Little carousel object with touch events and slide animation in plain javascript (with a little of jQuery)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="carousel-container"> | |
<div class="carousel" id="my-carousel-id" carousel> | |
<!-- your templating engine for loop --> | |
<div class="carousel-slide"> | |
<img class="carousel-slide-background" src="one-image" alt="Image"> | |
<h1 class="carousel-slide-title">some title here</h1> | |
<p class="carousel-slide-subtitle">some subtitle here</p> | |
</div> | |
<!-- end for --> | |
<ul class="carousel-dots"> | |
<!-- your templating engine for loop --> | |
<li class="carousel-dots-dot" data-index="index-from-your-for-loop"></li> | |
<!-- end for --> | |
</ul> | |
</div> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// LittleCarousel.js | |
// | |
// id -> string used to select the html element for carousel (not the container, but the carousel | |
// options -> object (but could be just a variable) | |
// - options.duration -> time in miliseconds to use in the setInterval (used for advancing slides automatically) | |
// | |
function Carousel(id, options) { | |
var ca = this; | |
options = options || {}; | |
ca.$carousel = $('#' + id); | |
if (ca.$carousel[0]) { | |
ca.$slides = this.$carousel.find('.carousel-slide'); | |
ca.$dots = this.$carousel.find('.carousel-dots-dot'); | |
ca.duration = parseInt(options.duration, 10) || 10000; | |
ca.index = 1; | |
ca.transitioning = false; | |
ca.init(); | |
ca.initTouchEvents(); | |
} | |
} | |
Carousel.prototype.init = function() { | |
var ca = this; | |
ca.$slides[0].style.left = '0'; | |
ca.$slides[0].style.display = 'block'; | |
ca.$dots[0].className += ' active'; | |
$(document).on('click', '.carousel-dots-dot', function(e) { | |
var newIndex = e.target.dataset.index; | |
ca.resetTimer(); | |
ca.showSlide(parseInt(newIndex, 10)); | |
}); | |
ca.resetTimer(); | |
} | |
Carousel.prototype.resetTimer = function() { | |
var ca = this; | |
clearInterval(ca.timer); | |
ca.timer = setInterval(function() { | |
ca.next(); | |
}, ca.duration); | |
} | |
Carousel.prototype.showSlide = function(n) { | |
var ca = this; | |
ca.transitioning = true; | |
var lastIndex = ca.index; | |
var newIndex = n; | |
var nextIndex = n + 1; | |
var slidesLength = ca.$slides.length; | |
var animationDuration = 1500; | |
var animationType = 'easeInOutQuad'; | |
var goTo = '100%'; | |
if (lastIndex === newIndex) | |
lastIndex--; | |
if (newIndex > slidesLength) | |
newIndex = 1; | |
if (newIndex < 1) | |
newIndex = slidesLength; | |
if (nextIndex > slidesLength) | |
nextIndex = 1; | |
if (newIndex > lastIndex) | |
goTo = '-100%'; | |
// Move past slide | |
// Hide when animation is done | |
if (lastIndex >= 1 && lastIndex <= slidesLength) { | |
$(ca.$slides[lastIndex - 1]).animate({ left: goTo }, animationDuration, animationType, function() { | |
ca.$slides[lastIndex - 1].style.display = 'none'; | |
}); | |
} | |
// Remove active from dots and slides | |
// Prepare following and previous slides | |
var i; | |
for(i = 1; i <= slidesLength; i++) { | |
ca.$dots[i - 1].className = ca.$dots[i - 1].className.replace(' active', ''); | |
var moveTo = i > newIndex ? '100%' : '-100%'; | |
if (i !== newIndex && i !== lastIndex) { | |
ca.$slides[i - 1].style.left = moveTo; | |
} | |
} | |
// Animate new slide | |
ca.$slides[newIndex - 1].style.display = 'block'; | |
$(ca.$slides[newIndex - 1]).animate({ left: 0 }, animationDuration, animationType, function() { | |
ca.transitioning = false; | |
}); | |
// Add active to current dot | |
ca.$dots[newIndex - 1].className += ' active'; | |
ca.index = newIndex; | |
return ca.index; | |
} | |
Carousel.prototype.next = function() { | |
return this.showSlide(this.index + 1); | |
} | |
Carousel.prototype.prev = function() { | |
return this.showSlide(this.index - 1); | |
} | |
Carousel.prototype.initTouchEvents = function() { | |
var ca = this; | |
var minSwipeTime = 200; | |
if ("ontouchstart" in window) { | |
var touchStart = function(evt) { | |
var startTime = (new Date()).getTime(); | |
var startX = evt.changedTouches[0].pageX; | |
var touchEnd = function(evt) { | |
document.removeEventListener("touchend", touchEnd); | |
var diffX = evt.changedTouches[0].pageX - startX; | |
var elapsed = (new Date()).getTime() - startTime; | |
if (elapsed < minSwipeTime && Math.abs(diffX) > 50) { | |
if (ca.transitioning) | |
return | |
ca.resetTimer(); | |
(diffX < 0) ? ca.next() : ca.prev(); | |
} | |
} | |
document.addEventListener("touchend", touchEnd); | |
}; | |
ca.$carousel[0].addEventListener("touchstart", touchStart); | |
} | |
} | |
$.easing.jswing = $.easing.swing; | |
$.extend($.easing, { | |
def: 'easeOutQuad', | |
easeInOutQuad: function (x, t, b, c, d) { | |
if ((t/=d/2) < 1) return c/2*t*t + b; | |
return -c/2 * ((--t)*(t-2) - 1) + b; | |
} | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Full page carousel | |
// In case you got a header | |
$header-height: some-size; | |
// Set your breakpoint | |
$screen-md: 992px; | |
// To handle media queries | |
@mixin media-breakpoint-up($breakpoint) { | |
@media (min-width: $breakpoint) { | |
@content; | |
} | |
} | |
.carousel { | |
height: 100%; | |
&-container { | |
overflow: hidden; | |
position: absolute; | |
width: 100%; | |
height: calc(100% - #{$header-height}); | |
top: $header-height; | |
} | |
&-slide { | |
position: absolute; | |
height: 100%; | |
width: 100%; | |
left: 100%; | |
display: none; | |
&-background { | |
position: relative; | |
top: 0; | |
min-width: 100%; | |
min-height: 100%; | |
max-width: none; // To disable default rule for img tags | |
height: 100%; | |
// For mobile | |
width: auto; | |
// To make it full page | |
@include media-breakpoint-up($screen-md) { | |
width: 100%; | |
} | |
} | |
&-title { | |
position: absolute; | |
margin: 0; | |
width: 100%; | |
font-size: 38px; | |
color: #fff; | |
// Mobile | |
bottom: #{$header-height + 70px}; | |
@include media-breakpoint-up($screen-md) { | |
bottom: calc(#{$header-height} + 20%); | |
} | |
} | |
&-subtitle { | |
position: absolute; | |
margin: 0; | |
width: 100%; | |
color: #fff; | |
font-weight: 100; | |
// Mobile | |
bottom: #{$header-height + 40px}; | |
@include media-breakpoint-up($screen-md) { | |
bottom: calc(#{$header-height} + 10%); | |
} | |
} | |
} | |
&-dots { | |
position: absolute; | |
bottom: #{$header-height + 10px}; | |
width: 100%; | |
&-dot { | |
border: 1px solid #fff; | |
border-radius: 10px; | |
display: inline-block; | |
width: 10px; | |
height: 10px; | |
cursor: pointer; | |
&.active { | |
background-color: #fff; | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function($) { | |
$(function() { | |
var myCarousel = new Carousel('my-carousel-id', { duration: 6000 }); | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment