How to change transition style in a slider from fade to slide - javascript

I've created a slideshow to put in the beggining of my website but, as I am new in this stuff, I've created it connecting snippets I've found in some websites, and now the image transition style is fade and I want to change it to slide, and I don't know how to do it. Can anyone help me, please? Here is the slider code:
<div class="slider" id="main-slider">
<!-- outermost container element -->
<div class="slider-wrapper">
<!-- innermost wrapper element -->
<img src="http://lorempixel.com/1024/400/animals" alt="First" class="slide" style="width:100%" />
<!-- slides -->
<img src="http://lorempixel.com/1024/400/business" alt="Second" class="slide" style="width:100%" />
<img src="http://lorempixel.com/1024/400/city" alt="Third" class="slide" style="width:100%" />
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
</div>
<script type="text/javascript">
(function() {
function Slideshow(element) {
this.el = document.querySelector(element);
this.init();
}
Slideshow.prototype = {
init: function() {
this.wrapper = this.el.querySelector(".slider-wrapper");
this.slides = this.el.querySelectorAll(".slide");
this.previous = this.el.querySelector(".slider-previous");
this.next = this.el.querySelector(".slider-next");
this.index = 0;
this.total = this.slides.length;
this.timer = null;
this.nextButton = this.el.querySelector(".next");
this.prevButton = this.el.querySelector(".prev");
this.action();
this.stopStart();
this.nextSlide();
this.prevSlide();
},
_slideTo: function(slide) {
var currentSlide = this.slides[slide];
currentSlide.style.opacity = 1;
for (var i = 0; i < this.slides.length; i++) {
var slide = this.slides[i];
if (slide !== currentSlide) {
slide.style.opacity = 0;
}
}
},
action: function() {
var self = this;
self.timer = setInterval(function() {
self.index++;
if (self.index == self.slides.length) {
self.index = 0;
}
self._slideTo(self.index);
}, 10000);
},
stopStart: function() {
var self = this;
self.el.addEventListener("mouseover", function() {
clearInterval(self.timer);
self.timer = null;
}, false);
self.el.addEventListener("mouseout", function() {
self.action();
}, false);
},
nextSlide: function() {
var self = this;
self.nextButton.addEventListener("click", function() {
clearInterval(self.timer);
self.timer = null;
self.index++;
if (self.index == self.slides.length) {
self.index = 0;
}
self._slideTo(self.index);
});
},
prevSlide: function() {
var self = this;
self.prevButton.addEventListener("click", function() {
clearInterval(self.timer);
self.timer = null;
self.index--;
if (self.index == -1) {
self.index = self.slides.length - 1;
}
self._slideTo(self.index);
});
}
};
document.addEventListener("DOMContentLoaded", function() {
var slider = new Slideshow("#main-slider");
});
})();
</script>
<style type="text/css">
html,
body {
margin: 0;
padding: 0;
}
.slider {
width: 100%;
}
.slider-wrapper {
width: 100%;
height: 500px;
position: relative;
}
.slide {
float: left;
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 3s linear;
}
.slider-wrapper>.slide:first-child {
opacity: 1;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -22px;
padding: 16px;
color: black;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
#media screen and (max-width: 480px) {
img {
max-height: 300px
}
.prev,
.next {
top=30%
}
}
</style>
Thanks,
Tom

Related

Carousel css3 animation acting weird

I've created this 3 item vertical carousel, and need to correct the transition.
My current project can be seen here:
http://hotelfjordgaarden.dk.test.vjm.dk/
I want to create the transition from this pen (the regular swipe/fade carousel transition):
https://codepen.io/marcusmichaels/pen/yGGoLM
If anyone could help me solve this, I would be so greatful!
Thanks in advance!
My HTML:
<div class="container">
<div class="frontpage__content__carousel">
<div class="frontpage__content__carousel__list">
<div class="frontpage__content__carousel__list__item" data-href="//google.com">
<a href="//google.com">
<p class="h1">
Heading
</p>
<p class="sub">
Subheading
</p>
</a>
</div>
<div class="frontpage__content__carousel__list__item" data-href="//google.com">
<a href="//google.com">
<p class="h1">
Heading
</p>
<p class="sub">
Subheading
</p>
</a>
</div>
<div class="frontpage__content__carousel__list__item" data-href="//google.com">
<a href="//google.com">
<p class="h1">
Heading
</p>
<p class="sub">
Subheading
</p>
</a>
</div>
<div class="frontpage__content__carousel__list__item" data-href="//google.com">
<a href="//google.com">
<p class="h1">
Heading
</p>
<p class="sub">
Subheading
</p>
</a>
</div>
<div class="frontpage__content__carousel__list__item" data-href="//google.com">
<a href="//google.com">
<p class="h1">
Heading
</p>
<p class="sub">
Subheading
</p>
</a>
</div>
</div>
<div class="frontpage__content__carousel__navigation">
<div class="prev icon" id="jsGoToPrev"></div>
<div class="next icon" id="jsGoToNext"></div>
</div>
</div>
</div>
My SASS:
.frontpage {
width: 100%;
overscroll-behavior: none;
.header {
background: white;
display: flex;
width: 100%;
justify-content: center;
align-items: center;
height: 138px;
}
.frontpage__content {
width: 100%;
height: 100%;
display: flex;
text-align: center;
align-items: center;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
position: relative;
overflow: hidden;
#media only screen and (max-width: #screen-sm-max) {
> div {
width: 100%;
margin-left: auto;
margin-right: auto;
}
}
&::before {
content: '';
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #8fa2a6;
z-index: -2;
}
&__video {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: -1;
opacity: 0.4;
}
// carousel wrapper
&__carousel {
overflow: hidden;
& * {
box-sizing: border-box;
}
// carousel
&__list {
overflow: hidden;
transform-style: preserve-3d;
&__item {
// disable user selection
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
opacity: 0;
position: absolute;
top: 0;
left: 0;
transition: transform .5s, top .5s, z-index .5s;
width: 100%;
z-index: -100;
margin: auto;
a {
.h1 {
font-size: 18px;
color: white;
text-transform: uppercase;
margin: 0;
}
.sub {
font-size: 14px;
font-weight: 500;
color: white;
margin: 0;
}
}
&.prev {
transform: translateY(-100%);
z-index: 800;
opacity: 0.5;
}
&.next {
transform: translateY(420%);
#media only screen and (min-width: #screen-lg) {
transform: translateY(500%);
}
z-index: 800;
opacity: 0.5;
}
&.active {
opacity: 1;
position: relative;
z-index: 900;
padding: 40px 0;
margin: 20px 0;
border: 1px solid rgba(255, 255, 255, 0.4);
border-left: none;
border-right: none;
a {
.h1 {
font-size: 18px;
}
.sub {
font-size: 16px;
}
}
}
}
}
&__navigation {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
display: none;
position: relative;
.icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
font-size: 20px;
border-radius: 50%;
border: 2px solid rgba(white, 0.5);
color: rgba(white, 0.5);
font-weight: 400;
font-family: 'Font Awesome 5 Pro';
position: fixed;
left: 60px;
cursor: pointer;
}
.prev {
top: 40%;
&::before {
content: '\f176';
}
}
.next {
top: 70%;
&::before {
content: '\f175';
}
}
}
}
}
// tablet portrait
#media only screen and (min-width: #screen-sm) {
height: 100vh;
.frontpage__content__carousel__list__item {
a {
.h1 {
font-size: 30px;
}
.sub {
font-size: 10px;
}
}
&.active {
a {
.h1 {
font-size: 40px;
}
.sub {
font-size: 24px;
}
}
}
}
}
// tablet landscape
#media only screen and (min-width: #screen-md) {
.frontpage__content__carousel__list__item {
a {
.h1 {
font-size: 30px;
}
.sub {
font-size: 10px;
}
}
&.active {
a {
.h1 {
font-size: 40px;
}
.sub {
font-size: 24px;
}
}
}
}
}
// desktop
#media only screen and (min-width: #screen-lg) {
.frontpage__content__carousel__navigation {
display: block;
}
.frontpage__content__carousel__list__item {
a {
.h1 {
font-size: 30px;
}
.sub {
font-size: 10px;
}
}
&.active {
a {
.h1 {
font-size: 60px;
}
.sub {
font-size: 30px;
}
}
}
}
}
}
My Javascript:
if ($('.frontpage__content').length > 0) {
$(document).ready(function () {
adjustFrontpageContentHeight();
});
$(window).resize(function () {
adjustFrontpageContentHeight();
});
function adjustFrontpageContentHeight() {
var $windowHeight = $(window).height();
var $headerHeight = $('.header').height();
$('.frontpage__content').height($windowHeight - $headerHeight);
}
(function ($) {
var carousel = $('.frontpage__content__carousel');
var list = $('.frontpage__content__carousel__list');
var items = $('.frontpage__content__carousel__list__item');
var totalItems = items.length;
var slide = 0;
var moving = true;
var itemClassName = 'frontpage__content__carousel__list__item';
function getElements() {
var prev = $('.frontpage__content__carousel__list__item.prev');
var active = $('.frontpage__content__carousel__list__item.active');
var next = $('.frontpage__content__carousel__list__item.next');
var beforePrev;
if (prev.prev().length > 0) {
beforePrev = prev.prev();
} else if (prev.data('index') == 0) {
beforePrev = $('[data-index=' + (totalItems - 1) + ']')
} else {
beforePrev = $('[data-index=' + (prev.data('index') - 1) + ']');
}
var afterNext;
if (next.next().length > 0) {
afterNext = next.next();
} else {
afterNext = $('[data-index=' + (next.data('index') + 1) + ']');
}
return {
beforePrev: beforePrev,
prev : prev,
active : active,
next : next,
afterNext : afterNext,
}
}
function setInitialClasses() {
items[totalItems - 1].className = itemClassName + ' prev';
items[0].className = itemClassName + ' active';
items[1].className = itemClassName + ' next';
}
function goToPrev() {
if (!moving) {
// if first slide, set as last slide, else -1
if (slide === 0) {
slide = (totalItems - 1);
} else {
slide--;
}
goToSlide(slide);
//prependPrev();
}
}
function goToNext() {
if (!moving) {
// if last slide, reset to 0, else +1
if (slide === (totalItems - 1)) {
slide = 0;
} else {
slide++;
}
goToSlide(slide);
//appendNext();
}
}
function goToSlide(slide) {
if (!moving) {
disableInteraction();
// Update the "old" adjacent slides with "new" ones
var newPrevious = slide - 1,
newNext = slide + 1,
oldPrevious = slide - 2,
oldNext = slide + 2;
// Checks and updates if the new slides are out of bounds
if (newPrevious <= 0) {
oldPrevious = (totalItems - 1);
} else if (newNext >= (totalItems - 1)) {
oldNext = 0;
}
// Checks and updates if slide is at the beginning/end
if (slide === 0) {
newPrevious = (totalItems - 1);
oldPrevious = (totalItems - 2);
oldNext = (slide + 1);
} else if (slide === (totalItems - 1)) {
newPrevious = (slide - 1);
newNext = 0;
oldNext = 1;
}
items.each(function() {
$(this).removeClass('active prev next');
});
// Add new classes
items[newPrevious].className = itemClassName + " prev";
items[slide].className = itemClassName + " active";
items[newNext].className = itemClassName + " next";
}
}
function disableInteraction() {
moving = true;
// set timeout to same as transition length
setTimeout(function () {
moving = false;
}, 500);
}
function setEventListeners() {
// click listeners
$('body').on('click', '#jsGoToPrev', function () {
goToPrev();
});
$('body').on('click', '#jsGoToNext', function () {
goToNext();
});
$('body').on('click', '.frontpage__content__carousel__list__item.prev', function () {
goToPrev();
});
$('body').on('click', '.frontpage__content__carousel__list__item.next', function () {
goToNext();
});
$('body').on('click', '.frontpage__content__carousel__list__item.active', function () {
if (!moving) {
window.location.href = $(this).data('href');
}
});
// mousewheel scroll listener
$('body').on('wheel', carousel.selector, function (e) {
if (e.originalEvent.deltaY < 0) {
goToPrev();
} else if (e.originalEvent.deltaY > 0) {
goToNext();
}
});
// touch scroll listener
var ts;
var te;
$('body').on('touchstart', function (e) {
ts = e.originalEvent.touches[0].clientY;
});
$('body').on('touchend', function (e) {
te = e.originalEvent.changedTouches[0].clientY;
if (ts > te+5) {
goToNext();
} else if (ts < te-5) {
goToPrev();
}
});
}
function prependPrev() {
list.prepend(getElements().prev);
}
function appendNext() {
list.append(getElements().next);
}
function initCarousel() {
// nullify links href after load - this is due to SEO
items.each(function () {
$(this).find('a').attr('href', 'javascript:void(0)');
});
setInitialClasses();
setEventListeners();
prependPrev();
moving = false;
}
$(document).ready(function () {
initCarousel();
});
})(jQuery);
}
What I eventually wounded up doing is:
Make my carousel DIV/container overflow: hidden, so I can have items inside which are hidden due to overflow.
I then use jQuery to scroll my div when a non-active item is clicked.
The entire script for the page is here:
if ($('.frontpage__content').length > 0) {
$('.frontpage__content__carousel__list__item ').click(function (e) {
if (!$(this).hasClass('active')) {
e.preventDefault();
var direction = 'up';
if ($(this).index() >= $('.frontpage__content__carousel__list__item.active').index()) {
direction = 'down';
}
$('.frontpage__content__carousel__list__item').removeClass('active');
$(this).addClass('active');
var _this = this;
var scrollTop = 0;
var items = $('.frontpage__content__carousel__list__item');
items.each(function (index, item) {
if ($(this).is($(_this).prev()) || $(_this).index() == 0) {
return false;
}
scrollTop += $(this).height();
});
$('.frontpage__content__carousel__list').stop().animate({
'scrollTop': scrollTop
});
}
});
function goToPrev() {
$('.frontpage__content__carousel__list__item.active').prev().trigger('click');
}
function goToNext() {
$('.frontpage__content__carousel__list__item.active').next().trigger('click');
}
$('#jsGoToPrev').click(function () {
goToPrev();
});
$('#jsGoToNext').click(function () {
goToNext();
});
$(window).resize(function () {
adjustFrontpageContentHeight();
});
function adjustFrontpageContentHeight() {
var $windowHeight = $(window).height();
var $headerHeight = $('.header').height();
$('.frontpage__content').height($windowHeight - $headerHeight);
}
var moving = false;
// mousewheel scroll listener
$('body').on('wheel', '.frontpage__content__carousel', function (e) {
if (!moving) {
moving = true;
setTimeout(function () {
moving = false;
}, 250);
if (e.originalEvent.deltaY < 0) {
goToPrev();
} else if (e.originalEvent.deltaY > 0) {
goToNext();
}
}
});
// touch scroll listener
var ts;
var te;
$('body').on('touchstart', '.frontpage__content__carousel', function (e) {
ts = e.originalEvent.touches[0].clientY;
});
$('body').on('touchend', '.frontpage__content__carousel', function (e) {
te = e.originalEvent.changedTouches[0].clientY;
if (ts > te + 5) {
goToNext();
} else if (ts < te - 5) {
goToPrev();
}
});
}

Prevent event overlap in custom jQuery image carousel

UPDATE: the solution I have posted below is not good enough, because it makes all the bullets except the active one non-responsive to clicks, instead of queueing them, so there is room for improvement.
I am working on a custom image carousel, using jQuery and CSS. My aim is to make it really lightweight but with (just) enough features: "bullets", auto-advance, responsiveness.
It works fine, but I have discovered a bug I was unable to fix: when I click 2 bullets in rapid succession - which means clicking the second before the transition triggered by the first is finished - the transitions overlap in a weird manner I can not describe but is visible below:
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false),
animationspeed = 1500,
animationInterval = 7000;
// Set (initial) z-index for each slide
var setZindex = function() {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
};
setZindex();
var displayImageBeforeClick = null;
var setActiveSlide = function() {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
};
var advanceFunc = function() {
if ($('.slider-nav li.activeSlide').index() + 1 != $('.slider-nav li').length) {
$('.slider-nav li.activeSlide').next().find('a').trigger('click');
} else {
$('.slider-nav li:first').find('a').trigger('click');
}
}
var autoAdvance = setInterval(advanceFunc, animationInterval);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
if (slidesCount > 1) {
/* Prepend the slider navigation to the slider
if there are at least 2 slides */
$elm.prepend('<ul class="slider-nav"></ul>');
// make a bullet for each slide
for (var i = 0; i < slidesCount; i++) {
var bullets = '<li>' + i + '</li>';
if (i == 0) {
// active bullet
var bullets = '<li class="activeSlide">' + i + '</li>';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
}
};
var slideUpDown = function() {
// set top property for all the slides
$(slides).not(displayImageBeforeClick).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
}, animationspeed);
$(displayImageBeforeClick).animate({
'top': "-100%"
}, animationspeed);
};
$('.slider-nav a').on('click', function(event) {
displayImageBeforeClick = $(".slider-container .active");
activeIdx = $(this).text();
if ($(slides[activeIdx]).hasClass("active")) {
return false;
}
$('.slider-nav a').closest('li').removeClass('activeSlide');
$(this).closest('li').addClass('activeSlide');
// Reset autoadvance if user clicks bullet
if (event.originalEvent !== undefined) {
clearInterval(autoAdvance);
autoAdvance = setInterval(advanceFunc, animationInterval);
}
setActiveSlide();
slideUpDown();
});
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
text-align: center;
position: absolute;
padding: 0;
margin: 0;
left: 10px;
right: 10px;
bottom: 2px;
z-index: 30;
}
.slider .slider-nav li {
display: inline-block;
width: 20px;
height: 3px;
margin: 0 1px;
text-indent: -9999px;
overflow: hidden;
background-color: rgba(255, 255, 255, .5);
}
.slider .slider-nav a {
display: block;
height: 3px;
line-height: 3px;
}
.slider .slider-nav li.activeSlide {
background: #fff;
}
.slider .slider-nav li.activeSlide a {
display: none;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=west" alt="">
</a>
</div>
</div>
</div>
How could I prevent this phenomenon I would call, for lack of a better term, an event crowding (overlap)?
You can chain your animations using jQuery deferred object and Promise. Here is the class allowing you to do it easily.
var Queue = function() {
var lastPromise = null;
this.add = function(callable) {
var methodDeferred = $.Deferred();
var queueDeferred = this.setup();
// execute next queue method
queueDeferred.done(function() {
// call actual method and wrap output in deferred
callable().then(methodDeferred.resolve)
});
lastPromise = methodDeferred.promise();
};
this.setup = function() {
var queueDeferred = $.Deferred();
// when the previous method returns, resolve this one
$.when(lastPromise).always(function() {
queueDeferred.resolve();
});
return queueDeferred.promise();
}
};
The fiddle is with the animations queued.
PS: I increase the size of the buttons to click more easily
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false),
animationspeed = 1500,
animationInterval = 7000;
// Set (initial) z-index for each slide
var setZindex = function() {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
};
setZindex();
var setActiveSlide = function() {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
};
var advanceFunc = function() {
if ($('.slider-nav li.activeSlide').index() + 1 != $('.slider-nav li').length) {
$('.slider-nav li.activeSlide').next().find('a').trigger('click');
} else {
$('.slider-nav li:first').find('a').trigger('click');
}
}
var autoAdvance = setInterval(advanceFunc, animationInterval);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
if (slidesCount > 1) {
/* Prepend the slider navigation to the slider
if there are at least 2 slides */
$elm.prepend('<ul class="slider-nav"></ul>');
// make a bullet for each slide
for (var i = 0; i < slidesCount; i++) {
var bullets = '<li>' + i + '</li>';
if (i == 0) {
// active bullet
var bullets = '<li class="activeSlide">' + i + '</li>';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
}
};
var Queue = function() {
var lastPromise = null;
this.add = function(callable) {
var methodDeferred = $.Deferred();
var queueDeferred = this.setup();
// execute next queue method
queueDeferred.done(function() {
// call actual method and wrap output in deferred
callable().then(methodDeferred.resolve)
});
lastPromise = methodDeferred.promise();
};
this.setup = function() {
var queueDeferred = $.Deferred();
// when the previous method returns, resolve this one
$.when(lastPromise).always(function() {
queueDeferred.resolve();
});
return queueDeferred.promise();
}
};
var queue = new Queue();
var slideUpDown = function(previousIdx, activeIdx) {
queue.add(function() {
return new Promise(function(resolve, reject) {
// set top property for all the slides
$(slides).not(slides[previousIdx]).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
}, animationspeed);
$(slides[previousIdx]).animate({
'top': "-100%"
}, animationspeed, 'swing', resolve);
})
})
};
var previousIdx = '0' // First slide
$('.slider-nav a').on('click', function(event) {
activeIdx = $(this).text();
// Disable clicling on an active item
if ($(slides[activeIdx]).hasClass("active")) {
return false;
}
$('.slider-nav a').closest('li').removeClass('activeSlide');
$(this).closest('li').addClass('activeSlide');
// Reset autoadvance if user clicks bullet
if (event.originalEvent !== undefined) {
clearInterval(autoAdvance);
autoAdvance = setInterval(advanceFunc, animationInterval);
}
setActiveSlide();
slideUpDown(previousIdx, activeIdx);
previousIdx = activeIdx
});
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
text-align: center;
position: absolute;
padding: 0;
margin: 0;
left: 10px;
right: 10px;
bottom: 2px;
z-index: 30;
}
.slider .slider-nav li {
display: inline-block;
width: 20px;
height: 6px;
margin: 0 1px;
text-indent: -9999px;
overflow: hidden;
background-color: rgba(255, 255, 255, .5);
}
.slider .slider-nav a {
display: block;
height: 6px;
line-height: 3px;
}
.slider .slider-nav li.activeSlide {
background: #fff;
}
.slider .slider-nav li.activeSlide a {
display: none;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=west" alt="">
</a>
</div>
</div>
</div>
Here is a possible fix, consisting of waiting for an animation to finish before starting another:
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false),
animationspeed = 1500,
animationInterval = 7000;
// Set (initial) z-index for each slide
var setZindex = function() {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
};
setZindex();
var displayImageBeforeClick = null;
var setActiveSlide = function() {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
};
var advanceFunc = function() {
if ($('.slider-nav li.activeSlide').index() + 1 != $('.slider-nav li').length) {
$('.slider-nav li.activeSlide').next().find('a').trigger('click');
} else {
$('.slider-nav li:first').find('a').trigger('click');
}
}
var autoAdvance = setInterval(advanceFunc, animationInterval);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
if (slidesCount > 1) {
/* Prepend the slider navigation to the slider
if there are at least 2 slides */
$elm.prepend('<ul class="slider-nav"></ul>');
// make a bullet for each slide
for (var i = 0; i < slidesCount; i++) {
var bullets = '<li>' + i + '</li>';
if (i == 0) {
// active bullet
var bullets = '<li class="activeSlide">' + i + '</li>';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
}
};
var animationStart = false;
var slideUpDown = function() {
animationStart = true;
// set top property for all the slides
$(slides).not(displayImageBeforeClick).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
}, animationspeed, function() {
animationStart = false;
});
$(displayImageBeforeClick).animate({
'top': "-100%"
}, animationspeed, function() {
animationStart = false;
});
};
$('.slider-nav a').on('click', function(event) {
if (animationStart) {
return false;
}
displayImageBeforeClick = $(".slider-container .active");
activeIdx = $(this).text();
if ($(slides[activeIdx]).hasClass("active")) {
return false;
}
$('.slider-nav a').closest('li').removeClass('activeSlide');
$(this).closest('li').addClass('activeSlide');
// Reset autoadvance if user clicks bullet
if (event.originalEvent !== undefined) {
clearInterval(autoAdvance);
autoAdvance = setInterval(advanceFunc, animationInterval);
}
setActiveSlide();
slideUpDown();
});
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
text-align: center;
position: absolute;
padding: 0;
margin: 0;
left: 10px;
right: 10px;
bottom: 2px;
z-index: 30;
}
.slider .slider-nav li {
display: inline-block;
width: 20px;
height: 3px;
margin: 0 1px;
text-indent: -9999px;
overflow: hidden;
background-color: rgba(255, 255, 255, .5);
}
.slider .slider-nav a {
display: block;
height: 3px;
line-height: 3px;
}
.slider .slider-nav li.activeSlide {
background: #fff;
}
.slider .slider-nav li.activeSlide a {
display: none;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=west" alt="">
</a>
</div>
</div>
</div>
You could use a queue: every time you click a bullet it add to the queue and execute the queue. Something like this:
{
let
transitionQueue = [],
transitioning = false;
function doTransition() {
displayImageBeforeClick = $(".slider-container .active");
$('.slider-nav a').closest('li').removeClass('activeSlide');
transitionQueue.shift().closest('li').addClass('activeSlide');
// Reset autoadvance if user clicks bullet
if (event.originalEvent !== undefined) {
clearInterval(autoAdvance);
autoAdvance = setInterval(advanceFunc, animationInterval);
}
setActiveSlide();
slideUpDown();
if (transitionQueue.length)
setTimeout(doTransition, animationSpeed)
else
transitioning = false;
}
function callTransition() {
if (!transitioning) {
transitioning = true;
doTransition();
}
}
$('.slider-nav a').click(function () {
transitionQueue.push($(this));
callTransition();
});
}
I haven't tested this, so...
While this not strictly answering your question, one way you could solve your actual problem is by handling your slider differently, consisting of moving the slider instead of the slides :
1) Make the slides container absolute, and it's container relative
.slider-homepage {
position: relative;
}
.slider .slider-container {
position: absolute;
}
.slider .slider-nav {
//position: absolute; Remove this
}
2) Instead of positionning the slides on click, move the slider container to the right position
var slideUpDown = function() {
$('.slider-container').stop().animate(
{top: activeIdx * slideHeight * -1},
{duration: animationspeed}
);
};
This way no image will ever overlap.
Here is the fiddle, the code can certainly be refactored but I didn't have too much time to look into it, will try to post a snippet here asap if you're ok with not leaving your original thing of moving slides instead of the slider.

Reset JavaScript interval instead of clearing it

I am working on a custom image carousel, using jQuery and CSS. My aim is to make it really lightweight but with enough features.
The script has an auto feature that I want to be stopped if the user clicks a bullet. I am using clearInterval for this purpose.
I would like to reset that interval, instead of clearing it. In other words, when the user clicks a bullet, I want that interval between two slides to be a "full" one (of 4 seconds).
Here is the code:
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false),
animationspeed = 300,
animationInterval = 4000;
// Set (initial) z-index for each slide
var setZindex = function() {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
};
setZindex();
var displayImageBeforeClick = null;
var setActiveSlide = function() {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
};
var advanceFunc = function() {
if ($('.slider-nav li.activeSlide').index() + 1 != $('.slider-nav li').length) {
$('.slider-nav li.activeSlide').next().find('a').trigger('click');
} else {
$('.slider-nav li:first').find('a').trigger('click');
}
}
var autoAdvance = setInterval(advanceFunc, animationInterval);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
for (var i = 0; i < slidesCount; i++) {
var bullets = '<li>' + i + '</li>';
if (i == 0) {
// active bullet
var bullets = '<li class="activeSlide">' + i + '</li>';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
};
var slideUpDown = function() {
// set top property for all the slides
$(slides).not(displayImageBeforeClick).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
}, animationspeed);
$(displayImageBeforeClick).animate({
'top': "-100%"
}, animationspeed);
};
$('.slider-nav a').on('click', function(event) {
event.preventDefault();
displayImageBeforeClick = $(".slider-container .active");
activeIdx = $(this).text();
if ($(slides[activeIdx]).hasClass("active")) {
return false;
}
$('.slider-nav a').closest('li').removeClass('activeSlide');
$(this).closest('li').addClass('activeSlide');
// Stop autoadvance if user clicks bullet
if (event.originalEvent !== undefined) {
clearInterval(autoAdvance);
}
setActiveSlide();
slideUpDown();
});
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
text-align: center;
position: absolute;
padding: 0;
margin: 0;
left: 10px;
right: 10px;
bottom: 2px;
z-index: 30;
}
.slider .slider-nav li {
display: inline-block;
width: 20px;
height: 3px;
margin: 0 1px;
text-indent: -9999px;
overflow: hidden;
background-color: rgba(255, 255, 255, .5);
}
.slider .slider-nav a {
display: block;
height: 3px;
line-height: 3px;
}
.slider .slider-nav li.activeSlide {
background: #fff;
}
.slider .slider-nav li.activeSlide a {
display: none;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<ul class="slider-nav"></ul>
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=west" alt="">
</a>
</div>
</div>
</div>
I have not figured out how to do that.
Like #epascarello said in a comment above, just clear & start again:
if (event.originalEvent !== undefined) {
clearInterval(autoAdvance);
autoAdvance = setInterval(advanceFunc, animationInterval);
}
later edit:
If the callback or the interval are not available anymore when restarting, it could help to "save" them in a closure:
function startInterval(func, delay) {
var id = setInterval(func, delay);
return {
stop: function() { clearInterval(id); },
restart: function() { clearInterval(id); id = setInterval(func, delay); }
};
}
var autoAdvance = startInterval(advanceFunc, animationInterval);
//later
autoAdvance.restart();

Custom jQuery carousel transition bug

I am working on a custom image carousel, with jQuery and CSS. I am trying to avoid using a multiple-features carousel plugin download from Github, for performance reasons.
My aim is to obtain a vertical transition, like the one on www.pcgarage.ro, but without using the plugin they (might) have used. For this purpose, I have written:
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
for (var i = 0; i < slidesCount; i++) {
var bullets = '' + i + '';
if (i == 0) {
// active bullet
var bullets = '' + i + '';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
}
// Set (initial) z-index for each slide
var setZindex = function() {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
}
setZindex();
$('.slider-nav a').on('click', function() {
activeIdx = $(this).text();
$('.slider-nav a').removeClass('activeSlide');
$(this).addClass('activeSlide');
setActiveSlide();
slideUpDown();
});
var setActiveSlide = function() {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
}
var slideUpDown = function() {
// set top property for all the slides
$(slides).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
});
}
body {
margin: 0;
padding: 0;
}
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
position: absolute;
left: 10px;
bottom: 10px;
z-index: 30;
}
.slider .slider-nav a {
display: block;
float: left;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 3px;
text-indent: -9999px;
background: #fff;
}
.slider .slider-nav a.activeSlide {
background: transparent;
border: 2px solid #fff;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<div class="slider-nav"></div>
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=north" alt="">
</a>
</div>
</div>
</div>
The problem with my code is the (obvious) white screen that accompanies every transition, whose cause I do not understand.
Where is my mistake?
I have added some variable and function to fix this issue kindly check the script.
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
for (var i = 0; i < slidesCount; i++) {
var bullets = '' + i + '';
if (i == 0) {
// active bullet
var bullets = '' + i + '';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
}
// Set (initial) z-index for each slide
var setZindex = function () {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
}
setZindex();
var displayImageBeforeClick = null;
$('.slider-nav a').on('click', function () {
displayImageBeforeClick = $(".slider-container .active");
activeIdx = $(this).text();
if($(slides[activeIdx]).hasClass("active")){ return false; }
$('.slider-nav a').removeClass('activeSlide');
$(this).addClass('activeSlide');
setActiveSlide();
slideUpDown();
});
var setActiveSlide = function () {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
}
var slideUpDown = function () {
// set top property for all the slides
$(slides).not(displayImageBeforeClick).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
});
$(displayImageBeforeClick).animate({
'top': "-100%"
});
}
body {
margin: 0;
padding: 0;
}
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
position: absolute;
left: 10px;
bottom: 10px;
z-index: 30;
}
.slider .slider-nav a {
display: block;
float: left;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 3px;
text-indent: -9999px;
background: #fff;
}
.slider .slider-nav a.activeSlide {
background: transparent;
border: 2px solid #fff;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<div class="slider-nav"></div>
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=north" alt="">
</a>
</div>
</div>
</div>
Add Transition to your ".slider .slider-container a" with a transition-duration and transition-timing-function.... for reference you can see https://www.w3schools.com/css/css3_transitions.asp

jQuery Countdown Timer is not displaying in browser

Have create a countdown timer by using jQuery. Hence, the countdown timer will only be activated after the user has navigated from the previous page to the current page. Therefore, in the current page, the blocks that are to be displayed will be
1.) Countdown Timer
2.) Scroll roller
Issue:
the Scroll roller is able to be displayed, however not the countdown Timer. What have I done wrong.
Code:
var count = 5;
function updateTimer() {
if (count > 0) {
$("#content").fadeOut('slow', function() {
$("#content").text(count);
$("#content").fadeIn();
count--;
});
} else if (count == 0) {
$("#content").fadeOut('slow', function() {
$("#content").text("Start!");
$("#content").fadeIn();
count--;
/*To display the canvas and countDown() function in 2 sec interval
after the fadein countdown is completed
*/
setTimeout(function() {
//canvasFunction();
//TEST: Countdown Gauge
(function($) {
var settings;
var timer;
var circleSeconds;
var layerSeconds;
var element;
var callbackFunction;
$.fn.final_countdown = function(options, callback) {
element = $(this);
// Element is not visibile
if (!element.is(':visible')) {
return;
}
var defaults = $.extend({
start: undefined,
end: undefined,
now: undefined,
selectors: {
value_seconds: '.clock-seconds .val',
canvas_seconds: 'canvas-seconds'
},
seconds: {
borderColor: '#654321',
borderWidth: '6'
},
}, options);
settings = $.extend({}, defaults, options);
if (settings.start === undefined) {
settings.start = element.data('start');
}
if (settings.end === undefined) {
settings.end = element.data('end');
}
if (settings.now === undefined) {
settings.now = element.data('now');
}
if (element.data('border-color')) {
settings.seconds.borderColor = element.data('border-color');
}
if (settings.now < settings.start) {
settings.start = settings.now;
settings.end = settings.now;
}
if (settings.now > settings.end) {
settings.start = settings.now;
settings.end = settings.now;
}
if (typeof callback == 'function') { // make sure the callback is a function
callbackFunction = callback;
}
responsive();
dispatchTimer();
prepareCounters();
startCounters();
};
function responsive() {
$(window).load(updateCircles);
$(window).on('redraw', function() {
switched = false;
updateCircles();
});
$(window).on('resize', updateCircles);
}
function updateCircles() {
layerSeconds.draw();
}
function convertToDeg(degree) {
return (Math.PI / 180) * degree - (Math.PI / 180) * 90
}
function dispatchTimer() {
timer = {
total: Math.floor((settings.end - settings.start) / 86400),
seconds: 60 - Math.floor((((settings.end - settings.now) % 86400) % 3600) % 60)
}
}
function prepareCounters() {
// Seconds
var seconds_width = $('#' + settings.selectors.canvas_seconds).width()
var secondsStage = new Kinetic.Stage({
container: settings.selectors.canvas_seconds,
width: seconds_width,
height: seconds_width
});
circleSeconds = new Kinetic.Shape({
drawFunc: function(context) {
var seconds_width = $('#' + settings.selectors.canvas_seconds).width()
var radius = seconds_width / 2 - settings.seconds.borderWidth / 2;
var x = seconds_width / 2;
var y = seconds_width / 2;
context.beginPath();
context.arc(x, y, radius, convertToDeg(0), convertToDeg(timer.seconds * 6));
context.fillStrokeShape(this);
$(settings.selectors.value_seconds).html(10 - timer.seconds);
},
stroke: settings.seconds.borderColor,
strokeWidth: settings.seconds.borderWidth
});
layerSeconds = new Kinetic.Layer();
layerSeconds.add(circleSeconds);
secondsStage.add(layerSeconds);
}
function startCounters() {
//var timer.seconds = 10;
var interval = setInterval(function() {
if (timer.seconds > 11) {
if (10 - timer.minutes == 0) {
clearInterval(interval);
if (callbackFunction !== undefined) {
callbackFunction.call(this); // brings the scope to the callback
}
return;
}
timer.seconds = 0;
} else {
timer.seconds++;
}
layerSeconds.draw();
}, 1000);
}
})(jQuery);
//TEST
$("#UserInteraction").show();
//countDown();
}, 2000)
});
$("#content").fadeOut();
} else {
$("#content").fadeOut();
clearInterval(interval);
}
}
setInterval(function() {
updateTimer()
}, 2000);
.countdown-container {
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
transform: translateY(-50%);
}
.clock-item .inner {
height: 0px;
padding-bottom: 100%;
position: relative;
width: 100%;
}
.clock-canvas {
background-color: rgba(255, 255, 255, .1);
border-radius: 50%;
height: 0px;
padding-bottom: 100%;
}
.text {
color: #fff;
font-size: 30px;
font-weight: bold;
margin-top: -50px;
position: absolute;
top: 50%;
text-align: center;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 1);
width: 100%;
}
.text .val {
font-size: 50px;
}
.text .type-time {
font-size: 20px;
}
#media (min-width: 768px) and (max-width: 991px) {
.clock-item {
margin-bottom: 30px;
}
}
#media (max-width: 767px) {
.clock-item {
margin: 0px 30px 30px 30px;
}
}
<div id="page2" class="img-wrapper" align="center" style=" position: relative; background-image: url(Image/Page2.png); background-repeat: no-repeat; width: 100%;height: 100%;">
<div id='content'></div>
<!-- <canvas id="canvas" width="300" height="300">
</canvas>
<canvas id="Counter" width="300" height="300">
</canvas>-->
<div id="scroller">
<p id="scrollTopId"></p>
</div>
<div id="UserInteraction" style="display:none" z-index="2">
<img id="roller" style="position: relative; top:1100px; width: 100%" src="image/rolling_pin/Rolling_Pin_Spin000.png" />
<img id="scroll" style="position:absolute; top: 1250px; left: 380px; overflow-y: auto;" src="image/Scroll.png">
</div>
</div>
You have display:none on the root div page2:
<div id="page2" class="img-wrapper" align="center" style=" position: relative; background-image: url(Image/Page2.png); background-repeat: no-repeat; display: none; width: 100%;height: 100%;">
Remove display:none or set it to display:block
https://jsfiddle.net/kebw53ue/1/

Categories

Resources