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>
Related
I was hoping a kind soul might be able to assist.
I have a slideshow which auto-plays, my intention is to have the next button act as a visual aid, highlighting the when the next frame is coming in.
sync with the autoPlay interval.
Right now, the update func concludes too early, which is the best I have managed to do. Typically I have the clearInterval and setInterval conflicting creating shuddering animations.
What am I doing wrong?
<!doctype html>
<html lang="en">
<head>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
.carousel_wrapper {
height: 50vh;
width: 100%;
position: relative;
}
.carousel_frame {
width: 100%; height: 100%;
}
.carousel_controls {
position: absolute;
bottom: 0;
left: 0;
}
.prev, .next {
height: 50px;
width: 100px;
background: aqua;
display: inline-block;
}
.next {
background: linear-gradient(to right, white 0%, aqua);
}
.carousel_frame:nth-child(1) {
background: red;
}
.carousel_frame:nth-child(2) {
background: blue;
}
.carousel_frame:nth-child(3) {
background: green;
}
</style>
<script>
window.addEventListener('DOMContentLoaded', () => {
const homepage_carousel = new carousel();
});
function carousel() {
const carousel = document.getElementsByClassName('.carousel_wrapper')[0];
const frames = [...document.getElementsByClassName('carousel_frame')];
const prev_button = document.getElementsByClassName('prev')[0];
const next_button = document.getElementsByClassName('next')[0];
this.frameIndex = 1;
prev_button.addEventListener('click', () => {
this.resetPlay();
this.move(-1);
})
next_button.addEventListener('click', () => {
this.resetPlay();
this.move(+1);
})
this.hideAll = () => {
frames.forEach((f) => {
f.style.display = 'none';
});
}
this.show = () => {
this.hideAll();
frames[this.frameIndex - 1].style.display = 'block';
this.update_bg();
}
this.move = (amount) => {
this.frameIndex += amount;
this.frameIndex = (this.frameIndex > frames.length ? 1 : (this.frameIndex < 1) ? frame.lengh : this.frameIndex);
this.show();
}
this.update_bg = () => {
let w = 1;
let test = setInterval(adjust, 10);
function adjust() {
if (w >= 100) {
clearInterval(test);
w = 0;
} else {
w++;
next_button.style.backgroundImage = `linear-gradient(to right, white ${w}%, aqua)`
}
}
setInterval(adjust, 3000);
}
this.autoPlay = () => {
this.move(+1)
this.update_bg();
}
this.resetPlay = () => {
// clearInterval(timer);
// timer = setInterval(this.autoPlay(), 4000);
}
this.show();
const timer = setInterval(this.autoPlay, 3000);
}
</script>
</head>
<body>
<div class='carousel_wrapper'>
<div class='carousel_frame'>
<span>Headline</span>
<span>Description</span>
<span>CTA</span>
</div>
<div class='carousel_frame'>
<span>Headline</span>
<span>Description</span>
<span>CTA</span>
</div>
<div class='carousel_frame'>
<span>Headline</span>
<span>Description</span>
<span>CTA</span>
</div>
<div class='carousel_controls'>
<span class='prev'>Previous</span>
<span class='next'>
Next
</span>
</div>
</div>
</body>
</html>
I have a function which counts the number of line breaks in a div, depending on the width of the window. While the functions works fine when placed in the $(window).on('resize') function, it does not work when put in $(document).ready() function. I want it to work right on page load, and also window resize, how do I support both?
JSFiddle
Javascript/jQuery:
// functions called in both document.ready() and window.resize
$(document).ready(function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Ready");
});
$(window).on('resize', function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Number of lines: " + lineCount);
});
// calculates the amount of lines required to hold the items
function getLineCount() {
var lineWidth = $('.line').width();
var itemWidthSum = 0;
var lineCount=1;
$('.item').each(function(index, element) {
if((lineWidth - itemWidthSum) > ($(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = $(element).outerWidth();
}
});
return lineCount;
}
// overlays rows for the amount of linebreaks
function postItems(lineCount){
var container = $('<div />');;
for(var i = 1; i <= lineCount; i++) {
container.append('<div class="line">' + i + '</div>');
}
$('.line-wrap').html(container);
}
You'll see at the start of the page, it incorrectly shows 17 lines, and then once you resize it will show the correct amount.
The issue lies in the first line of getLineCount(). Originally you had
var lineWidth = $('.line').width();
but no elements with the class "line" exist yet on your page (since they get added in your postItems() method. I changed it to
var lineWidth = $(".container").width();
instead, and now your code should be working. Snippet posted below:
$(document).ready(function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Ready");
});
$(window).on('resize', function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Number of lines: " + lineCount);
});
// calculates the amount of lines required to hold the items
function getLineCount() {
var lineWidth = $('.container').width();
var itemWidthSum = 0;
var lineCount=1;
$('.item').each(function(index, element) {
if((lineWidth - itemWidthSum) > ($(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = $(element).outerWidth();
}
});
return lineCount;
}
// overlays rows for the amount of linebreaks
function postItems(lineCount){
var container = $('<div />');;
for(var i = 1; i <= lineCount; i++) {
container.append('<div class="line">' + i + '</div>');
}
$('.line-wrap').html(container);
}
body {
text-align:center;
}
.answer {
position: fixed;
left: 0;
bottom: 0;
}
.container {
position: relative;
width: 50%;
margin: 0 auto;
border: 1px solid #e8e8e8;
display: inline-block;
}
.item {
height: 50px;
padding:0 10px;
background-color: #aef2bd;
float: left;
opacity:0.2;
white-space: nowrap;
}
.line-wrap {
position: absolute;
border: 1px solid red;
width: 100%;
height: 100%;
top:0; left: 0;
}
.line {
height: 50px;
width: 100%;
background-color: blue;
opacity:0.5;
color: white;
transition: all 0.5s ease;
}
.line:hover {
background-color: yellow;
color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item-wrap">
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
</div>
<div class="line-wrap">
</div>
</div>
<h1 class="answer"></h1>
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 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
I'm trying to create div boxes step by step and animate them for several times when a button is pressed. I have a running code, and everything is going well. It goes right to the endhost, then it goes left again to its original place. This is mainly what I do, and also the demo is found here: http://jsfiddle.net/LSegC/1/
Now what I want to do is to increase the number of whole animated DIVs one-by-one (as it is now) up to 3 Divs, but then have exponential increase on the total number of DIVs. So the total number of animated DIVs will be like 1, 2, 3, and then 4, 8, 16, etc.
Remember, my problem is not with the number being shown inside the DIV, it's actually that how many DIVS are being created! So I want for instance 8 DIVs, numbered from 1 to 8 animated. Hope it is now clear.
$(document).ready(function(){
$("button").click(function() {
var d = $(".t").fadeIn();
var speed = +$("#number1").val();
d.animate({left:'+=230px'}, speed);
d.animate({left:'+=230px'}, speed);
d.animate({top:'+=20px', backgroundColor: "#f09090", text:'12'}, speed/4, "swing", function() {
$('.span', this).fadeOut(100, function() {
$(this).text(function() {
return 'a' + $(this).text().replace('a', '');
}).fadeIn(100);
});
});
d.delay(1000).animate({left:'-=230px'}, speed);
d.animate({left:'-=230px'}, speed);
d.fadeOut().promise().done(function() {
d.last().after(function() {
var top = +$(this).css('top').replace('px', ''),
number = +$(this).data('number') + 1,
$clone = $(this).clone();
$clone.data('number', number).css('top', top + 20);
$clone.find('.span').text(number);
return $clone;
});
d.find('.span').text(function() {
return $(this).text().replace('a', '');
});
})
});
EDIT
Your code was too hard to manipulate as it was, I recreated the whole thing:
HTML:
<img id="streamline1" src="https://cdn3.iconfinder.com/data/icons/streamline-icon-set-free-pack/48/Streamline-04-48.png" />
<img id="LAN" src="https://cdn1.iconfinder.com/data/icons/ecqlipse2/NETWORK%20-%20LAN.png" />
<img src="https://cdn3.iconfinder.com/data/icons/streamline-icon-set-free-pack/48/Streamline-04-48.png" id="streamline" />
<div id="mid"></div>
<div id="bottom"></div>
<div>Speed (mS):
<input value="500" id="speed" type="number" style="position: relative"></input>
<button>Apply!</button>
<!-- dynamic area -->
<div class="packets"></div>
</div>
JS:
$(document).ready(function () {
var count = 0;
var items = 0;
var packetNumber = 0;
var speed = 0;
$("button").click(function () {
if (count < 4) {
items = items + 1;
count++;
} else {
items = items * 2;
}
speed = $("#speed").val();
createDivs(items);
animateDivs();
});
function createDivs(divs) {
packetNumber = 1;
var left = 60;
for (var i = 0; i < divs; i++) {
var div = $("<div class='t'></div>");
div.appendTo(".packets");
$("<font class='span'>" + packetNumber + "</font>").appendTo(div);
packetNumber++;
div.css("left",left+"px");
div.hide();
left += 20;
}
}
function animateDivs() {
$(".t").each(function () {
var packet = $(this);
packet.show();
packet.animate({
left: '+=230px'
}, speed);
packet.animate({
left: '+=230px'
}, speed);
packet.animate({
top: '+=20px',
backgroundColor: "#f09090",
text: '12'
}, speed / 4, "swing", function () {
$('.span').fadeOut(100, function () {
$(this).text(function () {
return 'a' + $(this).text().replace('a', '');
}).fadeIn(100);
});
});
packet.delay(1000).animate({left:'-=230px'}, speed);
packet.animate({left:'-=230px'}, speed);
}).promise().done(function(){
$(".packets").empty();});
}
});
CSS:
#bottom {
border: 1px dashed gray;
position: absolute;
left: 55px;
height: 20px;
width: 500px;
opacity: 0.5;
top: 30px;
z-index=-1;
}
#mid {
border: 1px dashed gray;
position: absolute;
left: 55px;
height: 20px;
width: 500px;
opacity: 0.5;
top: 10px;
z-index=-1;
}
.t {
display: inline-block;
position: absolute;
top: 10px;
left: 60px;
text-align: center;
vertical-align: middle;
width: 20px;
height: 20px;
background-color: lightgreen
}
#streamline {
width: 50px;
height: 50px;
right: 0px;
position: fixed;
left: 548px;
}
#streamline1 {
left: 0px;
width: 50px;
height: 50px;
}
#LAN {
width: 50px;
height: 50px;
left: 275px;
position: fixed;
}
.packets {
display: inline;
}
FIDDLE: http://jsfiddle.net/54hqm/3/
It was tough for me to follow the code also, but I cut it back quite a bit, came up with a "one-way" "empiric" approach. FIDDLE
The speed can be adjusted by the change in the increment (inc), but there are a variety of methods that can be used.
Can you be more specific about what you mean by "exponential"? Do you mean an exponential speed increase across the div, or rather a speed increase until you get to 50%, then a decrement in speed.
JS
$("button").click(function() {
var speed = 1000;
var d = $('.mover');
d.show();
var inc = 1;
for (var i=0; i<290; i=i+inc)
{
d.animate({ left: i,
easing: 'linear'}, 1);
if (inc < 11)
{
inc = inc + 1;
} else {
inc = inc - 1;
}
}
});