I am creating an HTML5 image carousel with three images. The transitions are done with TweenMax and TimeLine. I have two click events, one for next image and one for previous image, the next image function runs properly and is an infinite loop but the previous function stops after it goes through the images once. here is the code.
HTML:
<div id="expanded-state">
<div id="expanded-exit"></div>
<div id="close-btn"></div>
<button id="arrow-prev"></button>
<button id="arrow-next"></button>
<div id="theater">
<div class="theater"></div>
<div class="theater"></div>
<div class="theater"></div>
</div>
<div id="cta"></div>
<div id="footer"></div>
</div>
</div>
CSS:
.theater {
width: 970px;
height: 345px;
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
}
.theater:nth-child(1){
background: url(theater-01.jpg);
}
.theater:nth-child(2){
background: url(theater-02.jpg);
}
.theater:nth-child(3){
background: url(theater-03.jpg);
}
JS:
var $slides = $(".theater");
var currentSlide = 0;
function addListeners() {
arrowPrev.addEventListener('click', theaterScrollPrev);
arrowNext.addEventListener('click', theaterScrollNext);
}
function theaterScrollNext() {
tm.to( $slides.eq(currentSlide), 0.5, {left:"-970px"} );
if (currentSlide < $slides.length - 1) {
currentSlide++;
}
else {
currentSlide = 0;
}
tm.fromTo( $slides.eq(currentSlide), 0.5, {left: "970px"}, {left:"0px"} );
}
function theaterScrollPrev() {
tm.to( $slides.eq(currentSlide), 0.5, {left:"970px"} );
if (currentSlide < $slides.length - 1) {
currentSlide--;
}
else {
currentSlide = 0;
}
tm.fromTo( $slides.eq(currentSlide), 0.5, {left: "-970px"}, {left:"0px"});
}
I believe this should fix it but tell me if it does not
function theaterScrollPrev() {
console.log('previous clicked')
tm.to( $slides.eq(currentSlide), 0.5, {left:"970px"} );
if (currentSlide <= 0) {
currentSlide = $slides.length -1;
} else {
currentSlide--;
}
tm.fromTo( $slides.eq(currentSlide), 0.5, {left: "-970px"}, {left:"0px"} );
}
Codepen Fixed
Related
I want to set top:0(offset:0) when image come in viewport on single scroll (like on every single scroll next image set to top 0 of image position or offset 0 of image) after completing scrolling all image, continue scrolling the page. Any one have any idea, JavaScript code for this?
Here is link for try out JsFiddle
<div class="main-div">
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1601140958046-ce3c75269438?ixlib=rb-
1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80" />
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1559642147-97be7782c7b3?ixlib=rb-
1.2.1&auto=format&fit=crop&w=700&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1527435292159-ba44021581fa?ixlib=rb-
1.2.1&auto=format&fit=crop&w=634&q=80">
</div>
</div>
.main-div {
box-sizing: border-box;
}
.sticky-div {
position: sticky;
top:0;
height:100vh;
}
if($(window).width() >= 1024){
(function($) {
var selector = ".home-product-slider .product-item";
var $slides = $(selector);
var currentSlide = 0;
var isAnimating = false;
var stopAnimation = function() {
setTimeout(function() {
isAnimating = false;
}, );
};
var bottomIsReached = function($elem) {
var rect = $elem[0].getBoundingClientRect();
return rect.bottom <= $(window).height();
};
var topIsReached = function($elem) {
var rect = $elem[0].getBoundingClientRect();
return rect.top >= 0;
};
document.addEventListener(
"wheel",
function(event) {
var $currentSlide = $($slides[currentSlide]);
if (isAnimating) {
event.preventDefault();
return;
}
var direction = -event.deltaY;
if (direction < 0) {
// next
if (currentSlide + 1 >= $slides.length) return;
if (!bottomIsReached($currentSlide)) return;
event.preventDefault();
currentSlide++;
var $slide = $($slides[currentSlide]);
var offsetTop = $slide.offset().top;
isAnimating = false;
$("html, body").animate(
{
scrollTop: offsetTop,
behavior: 'smooth'
},
stopAnimation
);
} else {
// back
if (currentSlide - 1 < 0) return;
if (!topIsReached($currentSlide)) return;
event.preventDefault();
currentSlide--;
var $slide = $($slides[currentSlide]);
var offsetTop = $slide.offset().top;
isAnimating = false;
$("html, body").animate(
{
// scrollTop: offsetTop
},
stopAnimation
);
}
{ passive: false }
},
);
})(jQuery);
//home page slider script end here
}
You're looking for scroll snapping. On the container that controls the scrolling set the scroll-snap-type: y mandatory rule. Here you say that there should be snapped in the y axis and that the snap should be honored without exceptions.
On the elements that you want snapped, use the scroll-snap-align property. Set this to start indicating that the start of the element that scrolls into view should fall on the snap grid.
Do beware, the combination of position: sticky and scroll snapping could lead to buggy behavior on Safari iOS. source
html,
body {
margin: 0;
overflow: hidden;
}
.main-div {
box-sizing: border-box;
width: 1000px;
height: 100vh;
max-width: 100%;
overflow-y: auto;
scroll-snap-type: y mandatory;
}
.sticky-div {
position: sticky;
top: 0px;
width: 100%;
max-height: 100%;
height: 750px;
scroll-snap-align: start;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
<div class="main-div">
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1601140958046-ce3c75269438?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80" />
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1559642147-97be7782c7b3?ixlib=rb-1.2.1&auto=format&fit=crop&w=700&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1527435292159-ba44021581fa?ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1601140958046-ce3c75269438?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2134&q=80" />
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1559642147-97be7782c7b3?ixlib=rb-1.2.1&auto=format&fit=crop&w=700&q=80">
</div>
<div class="sticky-div">
<img src="https://images.unsplash.com/photo-1527435292159-ba44021581fa?ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80">
</div>
</div>
I have two or in future may be more divs with background images in css. I would like to fade them in and out in a loop.
I am trying to do something like this but it doesn`t work.
$(window).load(function(){
var divs = $('.fade');
function fade() {
var current = $('.current');
var currentIndex = divs.index(current),
nextIndex = currentIndex + 1;
if (nextIndex >= divs.length) {
nextIndex = 0;
}
var next = divs.eq(nextIndex);
next.stop().fadeIn(2000, function() {
$(this).addClass('current');
});
current.stop().fadeOut(2000, function() {
$(this).removeClass('current');
setTimeout(fade, 2500);
});
}
fade();
#one {
background-image: url("Test_bg.jpg");
margin-top: -150px;
min-height: 100%;
background-attachment: fixed;
}
#two {
background-image: url("Test_bg1.jpg");
margin-top: -150px;
min-height: 100%;
display: block;
background-attachment: fixed;
}
<div id="one" class="fade current">
</div>
<div id="two" class="fade">
</div>
You are mising }) at the end with causes syntax error
$(window).load(function(){
var divs = $('.fade');
function fade() {
var current = $('.current');
var currentIndex = divs.index(current),
nextIndex = currentIndex + 1;
if (nextIndex >= divs.length) {
nextIndex = 0;
}
var next = divs.eq(nextIndex);
next.stop().fadeIn(2000, function() {
$(this).addClass('current');
});
current.stop().fadeOut(2000, function() {
$(this).removeClass('current');
setTimeout(fade, 2500);
});
}
fade();
})
#one {
color: red
}
#two {
color: blue
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="one" class="fade current">a
</div>
<div id="two" class="fade">b
</div>
I'm trying to build a simple slideshow where an image slides out for two seconds whilst another image appears beneath it.
(function ready(fn) {
if (document.readyState != 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
})(init);
function init() {
var pictureCollection = document.getElementsByClassName('slideshowimg');
var pictureTracker = document.getElementsByClassName('trackPoint');
var count = 0;
//load initial pic
pictureCollection[count].style.animation = 'fadein10 0.1s forwards';
pictureTracker[count].style.backgroundColor = 'black';
//Fade
var fadetime = setInterval(function() {
fading()
}, 5000);
function fading() {
pictureCollection[count].style.animation = 'fadeout10 2s forwards';
pictureTracker[count].style.backgroundColor = 'gray';
if (count == pictureCollection.length - 1) {
count = -1;
}
count++;
pictureCollection[count].style.animation = 'fadein10 2s forwards';
pictureTracker[count].style.backgroundColor = 'black';
}
function fixer(direction) {
//remove event listener to ensure it doesn't reset EVERY transition
event.target.removeEventListener('transitionend', fixer);
pictureCollection[count].style.animation = 'fadeout10 0.1s forwards';
pictureCollection[count].style.transform = 'translateX(0px)';
//reset counter
if (count === 3 && direction === "right") {
count = 0;
return;
}
if (count === 0 && direction === "left") {
count = 3;
return;
}
if (direction === "right") {
count++;
}
if (direction === "left") {
count--;
}
}
//add event listener to handle user clicks to each lside
for (i = 0; i < pictureCollection.length; i++) {
pictureCollection[i].addEventListener('click', function() {
//cancel autofade
clearInterval(fadetime);
//check where on pic user clicked
if (event.clientX > event.target.width / 2) {
event.target.style.animation = 'nofade10 0.1s forwards';
pictureTracker[count].style.backgroundColor = 'gray';
if (count === 3) {
pictureCollection[0].style.animation = 'fadein5 0.1s forwards';
pictureTracker[0].style.backgroundColor = 'black';
} else {
//bring next pic forwards and unhide
pictureCollection[count + 1].style.animation = 'fadein5 0.1s forwards';
pictureTracker[count + 1].style.backgroundColor = 'black';
}
//slide out right
event.target.style.transform = 'translateX(250px)';
//ensure that when the picture slides out it repositions behind
pictureCollection[count].addEventListener('transitionend', fixer('right'));
}
//or going left . . .
else {
pictureCollection[count].style.animation = 'nofade10 0.1s forwards';
pictureTracker[count].style.backgroundColor = 'gray';
if (count === 0) {
pictureCollection[3].style.animation = 'fadein5 0.1s forwards';
pictureTracker[3].style.backgroundColor = 'black';
} else {
//bring next pic forwards and unhide
pictureCollection[count - 1].style.animation = 'fadein5 0.1s forwards';
pictureTracker[count - 1].style.backgroundColor = 'black';
}
//slide out left
event.target.style.transform = 'translateX(-' + pictureCollection[count].width + 'px)';
//ensure that when the picture slides out it repositions behind
pictureCollection[count].addEventListener('transitionend', fixer("left"), false);
}
});
}
}
.slideshowimg {
height: 100%;
width: 100%;
position: inherit;
z-index: 0;
opacity: 0;
transition: all 2s ease-in-out;
}
#sliderCase {
overflow: hidden;
position: absolute;
z-index: 5;
background-color: black;
height: 150px;
width: 225px;
}
.trackPoint {
height: 10px;
width: 10px;
margin: 0 2px;
background-color: gray;
display: inline-block;
border-radius: 2em;
text-align: center;
position: relative;
top: 160px;
left: 75px;
}
#keyframes fadein10 {
from {
opacity: 0;
}
to {
opacity: 1;
z-index: 10;
}
}
#keyframes fadeout10 {
from {
opacity: 1;
}
to {
opacity: 0;
z-index: 0;
}
}
#keyframes fadein5 {
from {
opacity: 0;
}
to {
opacity: 1;
z-index: 5;
}
}
#keyframes nofade10 {
from {
opacity: 1;
}
to {
opacity: 1;
z-index: 10;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf8'>
<script src='mainedit.js'></script>
<link rel='stylesheet' href='stylesedit.css' type='text/css'></link>
<title>Slideshow test</title>
</head>
<body>
<h1> Slideshow test: </h1>
<div id='sliderCase'>
<div style='background-color:red' class='slideshowimg'>pic 1</div>
<div style='background-color:blue' class='slideshowimg'>pic 2</div>
<div style='background-color:green' class='slideshowimg'>pic 3</div>
<div style='background-color:orange' class='slideshowimg'>pic 4</div>
</div>
<span class='trackPoint'></span>
<span class='trackPoint'></span>
<span class='trackPoint'></span>
<span class='trackPoint'></span>
</body>
</html>
It seems as if the transition end event is firing as the transition starts. Additionally the movement of slides seems to be inverted in the snippet, yet works locally.
I have used coloured divs in place of images for the sake of this example.
This isn't correct:
pictureCollection[count].addEventListener('transitionend', fixer("left"), false);
Here, you are calling and adding the return value of fixer("left") to the event listener, which isn't a valid value anyway.
Basically I have a structure like this, my goal is to animate 4 divs so that when you click on one the other slide out and when you click on the container they return to their initial positions.
var TL = new TimelineMax;
$('.quater').on('click', function () {
$faders = $('.container').find('.quater').not(this),
$faders.each(function () {
TL.to($(this), 1, {autoAlpha:0, x:50}, 0);
});
});
$('.container').on('click', function () {
TL.reverse();
TL.clear();
});
The problem is that if I omit the "TL.clear();" it will work just for the first ".quater" div clicked, if i put in the "TL.clear();" the animation will not reverse anymore.
jsFiddle.
Snippet:
var container = document.querySelector('.container');
var items = document.querySelectorAll('.item');
var duration = 0.6;
var ease = Expo.easeOut;
var numItems = items.length;
var i;
container.addEventListener('click', onContainerClicked, false);
for (i = 0; i < numItems; i += 1) {
(function(index){
items[index].timeline = new TimelineMax({ paused: true });
items[index].timeline.fromTo(items[index], duration, { y: 0, autoAlpha: 0.4 }, { y: -104, autoAlpha: 1, ease: ease });
items[index].addEventListener('click', onItemClicked, false);
}(i));
}
function onContainerClicked() { reverseAll(); }
function onItemClicked(e) {
reverseAll();
e.target.timeline.play();
}
function reverseAll() {
for (i = 0; i < numItems; i += 1) { items[i].timeline.reverse(); }
}
html, body {
margin: 0;
padding: 0;
}
.container {
background: #444;
width: 512px;
height: 104px;
}
.item {
float: left;
margin: 2px 0 0 2px;
width: 100px;
height: 100px;
}
.item:nth-child(odd) { background: #0cc; }
.item:nth-child(even) { background: #cc0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<div class="container"></div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
I've set up an animated slider using jQuery:
jsFiddle demo: http://jsfiddle.net/neal_fletcher/9zRDV/
The reason being I wanted to achieve a slight overhang on the slides, i.e. while viewing slide 1 you can see some of slide 2 etc. The slider works great, perfect in fact for what I'm after, now though I'm trying to figure out if it's possible to set up a pager for this slider, the aim of which being to click on a .slide-menu-item and the slider will slide to the relevant slide, if at all possible?
One other slight problem too, is it possible to animate the slider on load? Thus, the pager will slide every 5 seconds, but you can still navigate the slider using the pager / next and previous buttons?
Any suggestions would be greatly appreciated!
HTML:
<div class="outerwrapper">
<div class="innerwrapper">
<div class="inner-slide">SLIDE 01</div>
<div class="inner-slide">SLIDE 02</div>
<div class="inner-slide">SLIDE 03</div>
<div class="inner-slide">SLIDE 04</div>
<div class="inner-slide">SLIDE 05</div>
<div class="inner-slide">SLIDE 06</div>
<div class="inner-slide">SLIDE 07</div>
</div>
</div>
<ul id="slide-menu">
<li id="one" class="slide-menu-item">01</li>
<li id="two" class="slide-menu-item">02</li>
<li id="three" class="slide-menu-item">03</li>
<li id="four" class="slide-menu-item">04</li>
<li id="five" class="slide-menu-item">05</li>
<li id="six" class="slide-menu-item">06</li>
<li id="seven" class="slide-menu-item">07</li>
</ul>
<div id="left">LEFT</div>
<div id="right">RIGHT</div>
CSS:
.outerwrapper {
position: absolute;
left: 50%;
height: 250px;
width: 400px; margin-left: -225px;
border: 1px solid black;
overflow: hidden;
padding-left: 50px;
}
.innerwrapper {
height: 250px;
width: 4000px;
}
.inner-slide {
height: 250px;
width: 350px;
float: left;
background: silver;
}
.innerwrapper div:nth-child(odd) {
background: silver;
}
.innerwrapper div:nth-child(even) {
background: red;
}
#left, #right {
position: absolute;
cursor: pointer;
}
#left {
left: 10px; bottom: 10px;
}
#right {
right: 10px; bottom: 10px;
}
#slide-menu {
position: absolute;
top: 250px;
list-style: none;
}
.slide-menu-item {
display: inline-block;
width: 50px;
cursor: pointer;
}
jQuery:
var animating = false,
slideWidth = $('.inner-slide').width(),
$wrapper = $('.outerwrapper'),
slideIndex = 2,
slideLen = $('.inner-slide').length,
build = function() {
$firstClone = $('.inner-slide').eq(0).clone();
$secondClone = $('.inner-slide').eq(1).clone();
$preLastClone = $('.inner-slide').eq(slideLen - 2).clone();
$lastClone = $('.inner-slide').eq(slideLen - 1).clone();
$wrapper.find('.innerwrapper').append($firstClone, $secondClone).prepend($preLastClone, $lastClone);
$wrapper.animate({
scrollLeft: '+=' + slideWidth * slideIndex + 'px'
}, 0);
},
slide = function(dir, speed) {
if(!animating) {
animating = true;
dir == 'right' ? slideIndex++ : slideIndex--;
slideIndex == slideLen - 1 ? slideIndex == 0 : '';
if(slideIndex == 0 && dir == 'left') {
//if the slide is at the beginning and going left
slideIndex = slideLen + 1;
$wrapper.animate({
scrollLeft: slideIndex * slideWidth + 'px'
}, 0, function() {
animating = false;
});
slideIndex--;
} else if(slideIndex == slideLen + 2 && dir == 'right') {
//if the slide is at the end and going right
slideIndex = 1;
$wrapper.animate({
scrollLeft: slideIndex * slideWidth + 'px'
}, 0, function() {
animating = false;
});
slideIndex++;
}
$wrapper.animate({
scrollLeft: slideIndex * slideWidth + 'px'
}, speed, function() {
animating = false;
});
}
};
$(function() {
build();
$('#right, #left').on('click', function() {
slide($(this).attr('id'), 600)
});
});
Add the slideTo function:
slideTo = function (index, speed) {
slideIndex = index+1;
$wrapper.animate(
{scrollLeft: slideIndex * slideWidth + 'px'},
speed, function () {animating = false;}
);
}
Then call it when you click one of the page buttons:
$('.slide-menu-item').click(function() {
var toSlideIndex = Math.round($(this).text());
slideTo(toSlideIndex, 600);
});
And then, to make it slide automatically every 5 seconds, add this:
setInterval(function() {slide("right", 600);}, 5000);
JSFiddle demo: http://jsfiddle.net/9zRDV/3/
for example ?
$('#yourFavouriteIdForButtonThree').click(function(){
slide('three', 600)
});