How can I fire animations without queueing? - javascript

Each of these 3 divs travels 500px over 6000ms. After 4000ms, I want:
the red div to fade out over its last 2000ms
the green dive to fade in over 2000ms
the green div to start its journey of 500px
all simultaneously.
Then, after 8000ms, when the green div is 4000ms into its journey, I want:
the green div to fade out over its last 2000ms
the yellow dive to fade in over 2000ms
the yellow div to start its journey of 500px
all simultaneously.
Then, at 12000ms, when the yellow div is 4000ms into its journey, I want it to fade out over its last 2000ms of its journey.
It's about having total control with overlapping animations. I tried queue() and dequeue(), queue: false, setTimeout... I can't make heads or tails of it. How do I do this?
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<style>
div {
width:50px;
height:50px;
position:absolute;
left:0;
}
#div1 {background:red;top:0;}
#div2 {background:green;top:55px;}
#div3 {background:yellow;top:110px;}
</style>
</head>
<body>
<script>
$(document).ready(function(){
$("#div1").animate({left: "500px"}, 6000);
$("#div2").delay(4000).animate({left: "500px"}, 6000);
$("#div3").delay(8000).animate({left: "500px"}, 6000);
});
</script>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>

You can use css transition and start , step options of .animate()
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<style>
div {
width: 50px;
height: 50px;
position: absolute;
left: 0;
transition: opacity 2.5s ease;
}
#div1 {
background: red;
top: 0;
}
#div2 {
background: green;
top: 55px;
opacity:0;
}
#div3 {
background: yellow;
top: 110px;
opacity:0;
}
</style>
</head>
<body>
<script>
$(document).ready(function() {
function step(now, fx) {
var n = Math.round(now)
if (n === 250 || n === 251) {
$(this).css("opacity", 0)
}
}
function start() {
$(this).css("opacity", 1)
}
$("#div1").animate({
left: "500px"
}, {
duration: 6000,
step:step
});
$("#div2").delay(4000).animate({
left: "500px"
}, {
duration: 6000,
start:start,
step:step
});
$("#div3").delay(8000).animate({
left: "500px"
}, {
duration: 6000,
start:start,
step:step
});
});
</script>
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
</body>
</html>

Is this what you are trying to implement?
idArray = ['div1', 'div2', 'div3', 'div4'];
div = {};
//Create a flag for every item in list.
$(idArray).each(function(i, val) {
div['Action' + i] = false;
});
duration = 6000; //duration of each animation
overlap = 4000; //the time when overlap happens
fadeAt = 2000; //speed at which element appear/disappear
iLikeToMoveIt(0); //initialize animation
function iLikeToMoveIt(i) {
$now = $("#" + idArray[i]); //animation element
$next = $("#" + idArray[++i]); //next element
$now.fadeIn(fadeAt).animate({
left: "500px"
}, {
duration: 6000,
queue: false,
progress: function(animation, progress, remainingMs) {
//check if flag is not set
if (!div['Action' + i] && remainingMs < fadeAt) {
//set the flag
div['Action' + i] = true;
$(this).fadeOut(fadeAt);
if ($next.length) {
//call function for next div
iLikeToMoveIt(i);
}
}
}
});
}
div {
width: 50px;
height: 50px;
position: absolute;
left: 0;
}
.hide {
display: none;
}
#div1 {
background: red;
top: 0;
}
#div2 {
background: green;
top: 55px;
}
#div3 {
background: yellow;
top: 110px;
}
#div4 {
background: blue;
top: 165px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="div1"></div>
<div id="div2" class="hide"></div>
<div id="div3" class="hide"></div>
<div id="div4" class="hide"></div>

Related

How to save object position after animation in JavaScript?

I am trying to animate an object for a game in which the ball is supposed to move up, right, left and down on pressing user button. I am trying to achieve this by using .animate() function on the ball. But after every animation event, the ball resets to its initial position and does not continue moving from its "new" position. Is there any way to accomplish this?
Following is my condensed code snippet for simplicity:
/* Animation */
var item = document.getElementById('item');
var anim;
function myMoveLeft(){
anim=item.animate([
// keyframes
{ transform: 'translateX(0px)' },
{ transform: 'translateX(-60px)' }
], {
duration: 1000,
iterations: 1
});
}
function myMoveDown(){
anim=item.animate([
// keyframes
{ transform: 'translateY(0px)' },
{ transform: 'translateY(60px)' }
], {
duration: 1000,
iterations: 1
});
// anim.onfinish(()=>{console.log("onfinish ran")})
}
item.addEventListener('animationend', () => {
console.log('Animation ended');
});
button{
display:inline-block;
height:40px;
width:80px;
}
#myContainer {
width: 400px;
height: 400px;
position: relative;
background: lightgray ;
}
#item {
background: orange;
position: absolute;
right:30px;
top:30px;
height: 30px;
width: 30px;
border-radius:50%;
}
<p>
<button onclick="myMoveLeft()">Left</button>
<button onclick="myMoveDown()">Down</button>
</p>
<div id ="myContainer">
<div id="item"></div>
</div>
As seen, I have already tried using .onfinish() and Event Listener 'animationend' hoping I could update the new 'right' and 'top' position but it does not work. Not sure if that would be the right approach.
Could someone please suggest on how to save the element to a new position and animate it further from that new position?
PS: I am also open to suggestions/techniques if you feel there are other better ways to do this.
Thanks a lot in Advance!!
You can make the ball get the final transform value using the fill option, which is the same as animation-fill-mode in css animation.
For not override the transform when you do the next animation, you can save the x and y value as variables, and do any animation according to the current x and y state. (from x to x-60, instead from 0 to -60, etc.)
Example:
/* Animation */
var item = document.getElementById('item');
var anim;
var x=0, y=0;
function myMoveLeft(){
anim=item.animate([
// keyframes
{ transform: `translate(${x}px, ${y}px)` },
{ transform: `translate(${x-60}px, ${y}px)` }
], {
duration: 1000,
iterations: 1,
fill: 'forwards'
});
x -= 60;
}
function myMoveDown(){
anim=item.animate([
// keyframes
{ transform: `translate(${x}px, ${y}px)` },
{ transform: `translate(${x}px, ${y+60}px)` }
], {
duration: 1000,
iterations: 1,
fill: 'forwards'
});
y += 60;
// anim.onfinish(()=>{console.log("onfinish ran")})
}
item.addEventListener('animationend', () => {
console.log('Animation ended');
});
button{
display:inline-block;
height:40px;
width:80px;
}
#myContainer {
width: 400px;
height: 400px;
position: relative;
background: lightgray ;
}
#item {
background: orange;
position: absolute;
right:30px;
top:30px;
height: 30px;
width: 30px;
border-radius:50%;
}
<p>
<button onclick="myMoveLeft()">Left</button>
<button onclick="myMoveDown()">Down</button>
</p>
<div id ="myContainer">
<div id="item"></div>
</div>

Creating a simple, full-width, infinite carousel with jQuery

I'm creating a slider with jquery. I've looked on line if I could use any of the already made plugins, but none could do what I need to.
On a site I'm working on, I have a 1260px container where the content is.
The slider is fullwidth, and in the center is the active slide, and on the sides are previous and next slides that should serve as a previous and next click.
I plan to expand on that slider so that I have thumbnails beneath it, but for now I need to make the slider working.
HTML is (the images are 1260x520px)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Fullwidth Slider</title>
<link rel="stylesheet" href="style.css" type="text/css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="init.js"></script>
</head>
<body>
<div class="slider clearfix" data-autoplay="0" data-items="1" data-easing="linear" data-duration="750" data-height="520">
<div class=" single_slide" style="height: 520px; background-image: url('image.jpg'); background-size: cover; background-position: 0% 0%; background-repeat: no-repeat;">
<div class="slider_text">
</div>
</div>
<div class="single_slide active" style="height: 520px; background-image: url('image.jpg'); background-size: cover; background-position: 0% 0%; background-repeat: no-repeat;">
<div class="slider_text">
</div>
</div>
<div class=" single_slide" style="height: 520px; background-image: url('image.jpg'); background-size: cover; background-position: 0% 0%; background-repeat: no-repeat;">
<div class="slider_text">
</div>
</div>
<div class=" single_slide" style="height: 520px; background-image: url('image.jpg'); background-size: cover; background-position: 0% 0%; background-repeat: no-repeat;">
<div class="slider_text">
</div>
</div>
<div class=" single_slide" style="height: 520px; background-image: url('image.jpg'); background-size: cover; background-position: 0% 0%; background-repeat: no-repeat;">
<div class="slider_text">
</div>
</div>
</div>
</body>
</html>
Style css is:
/***************** Image Slider ****************/
.slider{
list-style: none;
display: block;
width: 100%;
overflow: hidden;
position: relative;
}
.slider .single_slide{
float: left;
display: block;
margin: 0;
padding: 0;
border-radius: 0px;
overflow: hidden;
opacity: 0.15;
width: 1260px;
cursor: pointer;
-webkit-transition: opacity 800ms ease-in-out;
transition: opacity 800ms ease-in-out;
}
.slider .single_slide.active{
opacity: 1;
cursor: default;
-webkit-transition: opacity 800ms ease-in-out;
transition: opacity 800ms ease-in-out;
}
jQuery code:
jQuery(document).ready(function($) {
$('.slider').each(function () {
var $slider = $(this);
var autoplay = $slider.data("autoplay");
var items = $slider.data("items");
var easing = $slider.data("easing");
var duration = $slider.data("duration");
var $single_slide = $slider.find('.single_slide');
var slider_height = $single_slide.css('height', $slider.data('height')+'px');
var left_offset = ($(window).width()-1260)/2;
$slider.css({'width' : $single_slide.length*1260+'px', 'left':- 1260+left_offset + 'px'});
$single_slide.eq(1).addClass('active');
var $prev = $('.active').prev();
var $next = $('.active').next();
function moveLeft() {
var $a = $('.active');
$a.removeClass('active').prev().addClass('active');
$slider.animate({
left: parseInt($slider.css('left'), 10) + $single_slide.outerWidth(true),
easing: easing,
step: items,
}, duration, function () {
$('.single_slide:first').before($('single_slide:last'));
});
}
function moveRight() {
var $a = $('.active');
$a.removeClass('active').next().addClass('active');
$slider.animate({
left: parseInt($slider.css('left'), 10) - $single_slide.outerWidth(true),
easing: easing,
step: items,
}, duration, function () {
$('.single_slide:last').after($('single_slide:first'));
});
}
$prev.click(function () {
moveLeft();
});
$next.click(function () {
moveRight();
});
if (autoplay == 1) {
setInterval(function () {
moveRight();
}, duration);
}
});
});
I've created a git repository as well, so you can download the html files.
I'm originally doing this for wordpress, but the workings is the same.
The problem is that it doesn't seem like the appending of the images once you click previous or next images works. Switching of the classes works, but the next and previous images are not changing when you click on them (I've done something similar but the prev/next buttons were fixed elements, so I could just target them all the time, but here they are changing)-
I think I got to the root of the issue with the previous and next selectors. They got cached once as a variable but were never updated when the active class changes to another slide - so the event listeners would stick to the elements that were initially set as siblings of the active slide :
var $prev = $('.active').prev();
var $next = $('.active').next();
Unfortunately this doesn't seem to work :
$('.active').prev().click(function() { ... });
But this almost does the trick :
$('.slider').find($('.single_slide').eq($('.active').index()+2)).click(function() {
moveLeft();
});
$('.slider').find($('.single_slide').eq($('.active').index()-1)).click(function() {
moveRight();
});
Update - made functional and infinite with the .detach() method and a delegated event listener :
http://codepen.io/anon/pen/aOoPgZ?editors=001
$('.slider').each(function() {
var slider = $(this);
var autoplay = slider.data('autoplay');
var items = slider.data('items');
var easing = slider.data('easing');
var duration = slider.data('duration');
var single_slide = slider.find('.single_slide');
var slider_height = single_slide.css('height', slider.data('height'));
var offset = ($(window).width()-1260)/2-1260;
$.each(single_slide, function(index) {
if (index == 0) $(this).addClass('img' + single_slide.length);
else $(this).addClass('img' + index);
});
slider.css({'width': single_slide.length*1260, 'left': offset});
single_slide
.eq(0).addClass('prev').end()
.eq(1).addClass('active').end()
.eq(2).addClass('next');
function moveLeft() {
$('.active').removeClass('active').prev().addClass('active');
slider.animate({
left: slider.position().left+single_slide.outerWidth(true),
easing: easing,
step: items
}, duration, function() {
$('.single_slide:last').detach().prependTo(slider);
slider.css('left', offset);
newNav();
});
}
function moveRight() {
$('.active').removeClass('active').next().addClass('active');
slider.animate({
left: slider.position().left-single_slide.outerWidth(true),
easing: easing,
step: items
}, duration, function() {
$('.single_slide:first').detach().appendTo(slider);
slider.css('left', offset);
newNav();
});
}
function newNav() {
$('.prev').removeClass('prev');
$('.next').removeClass('next');
$('.single_slide')
.eq(0).addClass('prev').end()
.eq(2).addClass('next');
}
$(document).on('click', '.prev', function() {
moveLeft();
});
$(document).on('click', '.next', function() {
moveRight();
});
if (autoplay == 1) {
setInterval(function() {
moveRight();
}, duration);
}
});
I'm sure there's room for some optimisation but it seems to do the trick. Has a feature to keep track of the images that may not be needed (but it's handy for debugging).
Now for some swipe support. :-D

Count back percentage using JQuery

I have the code below where I'd like to the numbers count back to 0% once hover the object out. Also I can't figure our how to make the value disappear again as it was on load. Could you please help me solve this.
Thanks in advance.
HTML
<div class="container">
<div class="fill" data-width="80%"></div>
</div>
<div class="container">
<div class="fill" data-width="50%"></div>
</div>
CSS
.container {
position: relative;
width: 300px;
height: 30px;
background-color: blue;
margin: 10px auto;
}
.fill {
height: 100%;
width: 0;
background-color: red;
line-height: 30px;
text-align: left;
z-index: 1;
text-align: right;
}
JQuery
$(function() {
$('.container').hover( function(){
var width=$(this).find(".fill").data('width');
$(this).find(".fill").animate({ width: width }, {
duration:800,
step: function(now, fx) {
$(this).html(Math.round(now) + '%');
}
});
},
function(){
$(this).find(".fill").animate({ "width": "0px" }, 800);
});
});
jsFiddle http://jsfiddle.net/zp8pe069/
jsBin demo
CSS: set overflow: hidden to .fill to prevent the text being visible after the animation ends.
HTML: remove % from the data attribute
JS and here you go. all you need:
$('.container').hover(function( e ){
var $fill = $(this).find(".fill");
var width = $fill.data('width');
$fill.stop().animate({width: e.type=="mouseenter" ? width+"%" : "0%" }, {
duration : 800,
step : function(now) {
$(this).html(Math.round(now) + '%') ;
}
});
});
Note also the use of the .stop() method, if you hover multiple time hysterically :) it'll prevent endless animations.

Jquery Text Animation

I am converting flash banner into html5 banner . Everything is working fine except the text animation. The text should work like this but my text is working fine but it is coming over the border it should work like my image animation which is working within the border. Here is my code http://jsfiddle.net/tU9LV/
<div id = "wrapper" >
<div id="mainContainer">
<div>
<img id="introImg" src="http://i.imgur.com/FClbHjn.png"/>
</div>
<div id="images">
<p id="headline1Txt" >Striped Bag</p><br />
<p id="headline2Txt" >$14</p><br />
<p id="headline3Txt" >Sale $25</p><br />
</div>
<div id="ctaBtn">
<button class="btn btn-primary" type="button">SHOP NOW</button>
</div>
</div>
</div>
$(document).ready(function () {
bannerAnimation();
});
function bannerAnimation(){
//Jquery Animation
$("#introImg").animate({ width: "120px",
height: "140px"
}, 1000);
$("#headline1Txt").animate({ left: "20" }, 500, function () {
$("#headline1Txt").animate({ left: "10" }, 200);
});
setTimeout(function () {
$("#headline2Txt").animate({ left: "20" }, 500, function () {
$("#headline3Txt").animate({ left: "20" }, 500, function () {
$("#headline3Txt").animate({ left: "10" }, 200);
});
$("#headline2Txt").animate({ left: "10" }, 200);
});
}, 1000);
}* {
margin:0;
padding:0;
}
#wrapper {
outline: 12px solid rgba(186,202,228 , 1);
width:285px;
height:235px;
position: absolute;
}
#mainContainer{
background: url('https://secure-ds.serving-sys.com/BurstingRes/Site-8188/Type-0/5fefb401-b187-4d82-b4db-cbd2ef29cc48.gif');
width:285px;
height:235px;
overflow: hidden;
position: fixed;
}
#introImg{
position:absolute;
top:80px;
left:150px;
right:100px;
opacity: 100;
}
#ctaBtn{
top:200px;
left:15px;
position:absolute;
}
#headline1Txt, #headline2Txt, #headline3Txt
{
position:absolute;
overflow: hidden;
margin:60px 8px;
left: -120px;
}
#headline2Txt, #headline3Txt
{
font-size:21px;line-height: 2.0;
}
#headline1Txt
{
font-size:26px;line-height: 1.5;
}
The simple solution for this if you can't change your background image is to layover a div for the borders..
http://jsfiddle.net/K3SXu/
I've added:
<div id="borders"></div>
to the html.
and:
#borders { position:absolute; top:0; left:0; z-index:999; border:12px solid rgba(186,202,228,1); width:285px; height:235px;}
to the css. and also removed the 'outline' property from the #wrapper.
it works :)

How to call a image class on a regular interval

I am having four classes inside each class a image is called
<div id="ban01" class="banner ban01">
</div>
<div id="ban02" class="banner ban02">
</div>
<div id="ban03" class="banner ban03">
</div>
<div id="ban04" class="banner ban04">
</div>
and my css class contains
.ban01 { background-image:url(../images/banner/01.jpg); }
.ban02 { background-image:url(../images/banner/02.jpg); }
.ban03 { background-image:url(../images/banner/03.jpg); }
.ban04 { background-image:url(../images/banner/04.jpg); }
and my Jquery is
$(document).ready(function () {
var totDivs = $(".banner ban03").length;
var currDiv = 0;
var myInterval = setInterval(function () {
if (currDiv > totDivs) {
clearInterval(myInterval);
return
}
$(".banner ban03").eq(currDiv).find('class').trigger("click");
currDiv++;
}, 2000);
});
how to call these classes in regular intervals sorry if i repeated the question again
html
<div id="ban01" class="banner ban01">
</div>
<div id="ban02" class="banner ban02">
</div>
<div id="ban03" class="banner ban03">
</div>
<div id="ban04" class="banner ban04">
</div>
style
.banner { height: 50px }
.ban01 { background: green }
.ban02 { background: blue }
.ban03 { background: red }
.ban04 { background: orange }
javascript
$(document).ready(function () {
var totDivs = $(".banner").length;
var currDiv = 0;
var myInterval = setInterval(change, 2000);
function change(){
$(".banner").hide().eq(currDiv).show();
currDiv = (currDiv + 1) % totDivs;
}
change();
});
http://jsfiddle.net/b2Btj/1/
Did you look on this answer... :-)
jquery-timed-change-of-item-class
Try this while I'm doing your coding. :-D
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<style type="text/css">
.a, .b, .c, .d, .e {
height: 120px;
width: 200px;
}
.a {
background-color: red;
}
.b {
background-color: green;
}
.c {
background-color: blue;
}
.d {
background-color: black;
}
.e {
background-color: yellow;
}
</style>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
</head>
<body>
<h1>Testing</h1>
<div id="test" class="a">How Are You Buddy?</div>
<script type="text/javascript">
$( document ).ready(function() {
var array = ['a','b','c','d','e'];//Here is your classes
var len = array.length;
var i=0;
function changeDivClass(d) {
$("#test").removeClass();
$("#test").addClass(array[d]);
}
setInterval(function() {
if(len>=i){
return changeDivClass(i++);
}else{
i=0;
$("#test").removeClass();
$("#test").addClass('a');
}
}, 5000);
});
</script>
</body>
</html>
#Maikay yes I want to rotate the images
Why use JavaScript to rotate image ?
This is possible with only css. Use the property : animation.
.imageRotate {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
-webkit-animation:spin 4s linear 1; // '1' for a single animation, if you need an infinite animation replace '1' by 'infinite'
-moz-animation:spin 4s linear 1;
animation:spin 4s linear 1;
}
#-moz-keyframes spin {
100% { -moz-transform: rotate(360deg); }
}
#-webkit-keyframes spin {
100% { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
100% { -webkit-transform: rotate(360deg);
transform:rotate(360deg);
}
}
<div id="ban01">
<img class="imageRotate" src="http://socialtalent.co/wp-content/uploads/blog-content/so-logo.png">
</div>
not sure what exactly the click trigger on the banner element will do, but maybe this helps:
$(document).ready(function () {
var totDivs = $(".banner").length;
var currDiv = 0;
var myInterval = setInterval(function() {
if (currDiv > totDivs) {
clearInterval(myInterval);
return;
}
$(".banner").eq(currDiv).trigger("click");
currDiv++;
}, 2000);
});
what you could do is that you could run a for loop if you know the counts of the "div"
for(var count=0;count<3;count++)
{
var totDivs = $(".banner ban0"+count).length;
var currDiv = 0;
var myInterval = setInterval(function () {
if (currDiv > totDivs) {
clearInterval(myInterval);
return
}
$(".banner ban0"+count).eq(currDiv).find('class').trigger("click");
currDiv++;
}, 2000);
}
May this could solve your issue .

Categories