jquery multiple function timing and repeat - javascript

I've created somewhat of a movie using jquery; it's composed of multiple functions representing each scene of the movie. Some scenes have to run longer than others. I'm having trouble creating a loop of the total movie. I've tried setting up setInterval several ways but they all seem to fail. To complicate things (for me at least) this is inside of a slide show that would ideally trigger the "next" button when it's complete.
feel free to knock the strategy I've used as the setTimeout for each scene was the only way I could figure out how to get each function to run after the next has ran for long enough. I couldn't figure out how to call each function with the amount of time that scene should run for vs. my current strategy of calling the next function after the previous one is complete.
Thanks for the direction
I think I need javascript to calculate the total time and call the atrAnime() in a setTimeout with the value but I can't seem to get it to calculate and pass back.
here's what I have:
$(document).ready(function(){
atrAnime(2000);
});
function atrAnime(dur){
first();
setTimeout(second, dur);
setTimeout(third, dur += 2000);
setTimeout(forth, dur += 2000);
setTimeout(fifth, dur += 2000);
setTimeout(sixth, dur += 6000);
setTimeout(seventh, dur += 2000);
setTimeout(eighth, dur += 2000);
setTimeout(ninth, dur += 2000);
setTimeout(tenth, dur += 2000);
setTimeout(end, dur += 3000);
};
Some scene examples:
function first(dur){
$('.pcba')
.css({
left: '150px'
})
.show();
$('.pcb_cad')
.css({
left: '275px',
top: '50px'
})
.show();
}
function second(dur){
$('.pcba').fadeOut();
$('.arrows')
.css({
left: '275px',
top: '50px'
})
.fadeIn();
$('.heatGenComps')
.css({
left: '325px',
top: '20px'
})
.fadeIn();
}
EDIT
My new ghetto solution has the last function in atrAnime() call as:
setTimeout(caller, dur += 2000);
};
and then another function
function caller(){
atrAnime(2000);
}

You are using some functions in your animations that actually provide a callback method once their action is completed. For example, the fadeIn/fadeOut functions have an "onComplete" callback for when the element has totally been shown/hidden -
$("#elem").fadeOut(function(){
alert('element has faded out!');
});
You could possible utilize these callback function, having them all call one central function that manages the sequence of execution. Each callback would trigger the next sequence. Both the show() and fadeIn() functions provide this callback as detailed in the documentation.
show()
fadeIn()

Wouldn't it better to nest all animations in callbacks? It just doesn't feel right relying on setTimeout :). What I mean is using the callbacks of the relevant animations so the next stage of animation will only fire once the previous one is finished. Something along the lines of:
$("firstElement").slideDown(500, function () {
$("secondElement").slideDown(500, function () {
$("thirdElement").slideDown(500, function () {
//etc
});
});
});

Related

Function with attr() function not executing all statements when there are multiple elements on screen created dynamically by a function

The function below creates a red dot on the right end of the screen, animate() to move it left and when clicked, its src file should be changed, along with a few other things as you can see below:
function spawnEnemy()
{
$("body").prepend("<img src='red_dot.png' class='enemies' id='enemy' style='left:calc(" + thewidth/2 + "px)'/>");
$("#enemy").attr("id", "enemy"+i);
$("#enemy"+i).css({"left" : thewidth+'px', "top" : (randomInt(10,500))+'px'});
$("#enemy"+i).animate({left :'-400px'}, 20000);
$("#enemy"+i).click(function()
{
var snd = new Audio("laser.mp3");
snd.play(); //function stops here
$("#enemy"+i).stop();
$("#enemy"+i).attr("src","explosion.gif");
$("#enemy"+i).css({"transform" : "scale(0.11,0.11)"});
setTimeout(function()
{
$('#enemy'+i).hide();
}, 350);
});
i+=1;
}
This function is executed every six seconds. If, however, the element is not clicked before a new element is created, then all of the elements when clicked stop executing at the line where I have placed a comment. I checked the console, and I couldn't find anything of value, although I know that the problem isn't with the ids as they all have different ids in the console, and since I can hear the sound from snd.play() and none of the effects of the statements after snd.play() are seen, I'm sure the problem lies there. This problem is only when multiple elements are created, as they all execute fine if I click the element before six seconds, i.e, before the function is executed again. Also, thewidth is just a pre-defined global var, so it's not related.
I'm very new to jquery, so I apologize if there's something obvious I'm missing.
Edit: Okay, now all the statements aren't executing even if there is only one element on the screen. I'm quite lost.
Ok, I think I see what's happening. You need to reference enemy with $(this) inside the callback, because i is in the encapsulating scope, which means it can change and break the internal scope of that callback:
While at it, I cleaned up your jQuery code a little to simplify it.
function spawnEnemy() {
$('<img />', {
id: 'enemy' + i,
src: 'red_dot.png',
className: 'enemies',
style: 'left: ' + thewidth / 2 + 'px; top: ' + randomInt(10,500) + 'px'
})
.prependTo($('body'));
.animate({left :'-400px'}, 20000);
.click(function() {
var snd = new Audio("laser.mp3");
snd.play(); //function stops here
$(this).stop();
$(this).attr("src","explosion.gif");
$(this).css({"transform" : "scale(0.11,0.11)"});
setTimeout(function() {
$(this).hide();
}.bind(this), 350);
});
i+=1;
}

jQuery - setInterval/clearInterval delay

I'm new to jQuery and am trying to fill a div over a certain amount of time. When that time is up I want to clear the div - pretty simple, right?
Summary: I click a button and the div starts filling(using animate({ height: "100%"}, workPeriod * 1000) over workPeriod which is 20 seconds. Once it's filled I want the div to be emptied. The div fills without issue and then once it's complete it takes about 5-10 seconds before it clears using animate({ height: "0%"}, workPeriod * 5000)
$('#begin').click(function () {
var workPeriod = 20
var start = new Date($.now());
var end = new Date(start.getTime() + 1000 * workPeriod);
var workInterval = setInterval(function () {
var currentDif = Math.floor((new Date($.now()) - end) / 1000) * -1;
if (currentDif < 0) {
$('#session-time').animate({
height: '0%'
}, 0);
clearInterval(workInterval);
//I want the animation above to occur instantly but it's happening several seconds after
//the clearInterval call
} else {
$('#session-time').animate({
height: '100%'
}, workPeriod * 1000);
}
}, 1000);
Question: How can I make the div empty immediately once it's full instead of waiting the 5-10 seconds?
btw, I'm very new to jQuery and still very much a beginner when it comes to programming so any advice will be well received
So, if you want to call another function/animation once your animation is complete, that functionality is already built into jQuery's animate function.
From the jQuery documentation:
$( "#clickme" ).click(function() {
$( "#book" ).animate({
opacity: 0.25,
left: "+=50",
height: "toggle"
}, 5000, function() {
// Animation complete.
});
});
I tried to get it to work with your code posted above, but I couldn't get your timer stuff to work. Nevertheless, I made this codepen, to show that the animation complete function does work when your complete function is another animation.

delay between animate.css animations

I'm kind of new to jQuery and I'm currently trying the following:
I'm using animate.css to animate a div. What I want to do now is to define a timing between fading in and fading out. For example:
Fade in > 3 sec delay > fade out
I'm using this function to dynamically add classes from animate.css to my object (#test).
$(document).ready(function () {
phase1('#test', 'bounceInLeft');
function phase1(element, animation) {
element = $(element);
element.addClass('animated ' + animation);
};
});
I'm trying to archive something like this:
phase1('#test', 'bounceInLeft');
3 sec delay
phase1('#test', 'bounceOutLeft');
1 sec delay
phase1('#test2', 'bounceInLeft');
.....
Any kind of help is really appreciated :) Thanks in advance!
Yes you setTimeout. Wrap your code within this section and adjust the timing with the amount of milliseconds that you want. This allows you to stagger code timings with multiple values..
This example will delay by three seconds, then one by five seconds..
setTimeout(function(){
// place your code in here
}, 3000);
setTimeout(function(){
// place your second bit of code in here
}, 5000);
Since you are using jQuery, you can use animation chains like that
(function($){
$(".move")
.animate({left:"+=200"},3000)
.delay()
.animate({left:"+=100"},3000);
})(jQuery);
See Example
Using jQuery chain events
$("#id").fadeIn(1000).delay(3000).fadeOut(1000);
This should work for you. All parameters specify time 1000=1Sec
http://jsfiddle.net/k8zq2fo6/
You can increase the chain
$("#id").fadeIn(1000).delay(3000).fadeOut(1000).delay(2000).fadeIn(1000).delay(3000).fadeOut(1000).delay(2000);
Try utilizing .queue()
$(function() {
// load `Animate.css`
$("style").load("https://raw.githubusercontent.com/"
+ "daneden/animate.css/master/animate.css");
// animation settings
var settings = [{
"bounceInLeft": 3000
}, {
"bounceOutLeft": 1000
}, {
"bounceInLeft": 3000
}];
$("#test").queue("bounce", $.map(settings, function(val, key) {
return function(next) {
var current = Object.keys(val)[0];
$(this)
// reset `className`
.attr("class", "")
// add `animated` , `current` `class`
.addClass("animated " + current);
// log `.queue("bounce")` iteration
console.log(this.className, current
, settings[key][current], $(this).queue("bounce"));
// "delay": `settings[key][current]` ,
// call `next` function in `.queue("bounce")`
setTimeout(next, settings[key][current]);
}
}))
.dequeue("bounce")
// do stuff when `.queue("bounce")` empty
.promise("bounce")
.then(function(elem) {
console.log(elem.queue("bounce"), "complete")
})
});
#test {
position: relative;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="test">abc</div>
<style></style>

One div to start contents to fadeToggle and another div to stop fadeToggle animation using javascript setInterval Function

My Fiddle:
http://jsfiddle.net/tmanundercover/62ap2/
CSS
#targetedDiv, #otherDiv {
border: 1px solid;
}
HTML
<div id="targetedDiv">&nbsp<span id="fakeCursor">|</span></div>
<br>
<div id="otherDiv">click here to stop</div>
Javascript
var fakeCursorInterval;
function startCursor(){
fakeCursorInterval = setInterval(function() {
$("#fakeCursor").fadeToggle("slow","swing");},20);
console.log("starting",fakeCursorInterval);
}
function stopCursor() {
clearInterval(fakeCursorInterval);
console.log("stopping",fakeCursorInterval);
}
$("#targetedDiv").click(function(){fakeCursorInterval = startCursor()});
$("#otherDiv").click(function(){stopCursor()});
console.log("outside",fakeCursorInterval);
My issue is that the console.log in stopCursor shows the interval as undefined.
I have looked at this post:
clear interval doesn't work
so i'm pretty sure this is a scope issue but I cannot figure it out my specific problem.
You're overriding the interval variable in your click handler.
$("#targetedDiv").click(function(){fakeCursorInterval = startCursor()});
This alone should work:
$("#targetedDiv").click(startCursor);
$("#otherDiv").click(stopCursor);
In addition to the issue mentioned by #koala_dev, the setInterval interval was 20, the fadeToggle interval was slow (which is 600). So, if you call stopCursor() after 1 second (1000 milliseconds), the fadeToggle would have been called 50 times. In that case, the fade animation will still last for 30 seconds (even that the setInterval have already been cleared). To resolve that issue, just use the same duration for both fadeToggle and setInterval (eg. 400 milliseconds). Additionally, you can call .stop() to stop the fade animation at the stopCursor(), and guarantee that it will really stop.
var fakeCursorInterval;
function startCursor() {
$("#fakeCursor").show().fadeToggle(400, "swing");
fakeCursorInterval = setInterval(function() {
$("#fakeCursor").fadeToggle(400,"swing");
}, 400);
console.log("starting", fakeCursorInterval);
}
function stopCursor() {
clearInterval(fakeCursorInterval);
$("#fakeCursor").hide().stop();
console.log("stopping", fakeCursorInterval);
}
$("#targetedDiv").click(startCursor);
$("#otherDiv").click(stopCursor);
console.log("outside", fakeCursorInterval);
See fiddle here.

Is there any way to make two jQuery animations run (properly) simultaneously?

I have an event listener that calls two animation actions. Unfortunately their starts are staggered by a small amount (e.g. the first in the function starts first).
Does anyone know a way to properly sync them up?
Here's my code:
$("#nav ul li a").hover(
function(){
$(lastBlock).children("div").animate({width: "0px"}, { queue:false, duration:400, easing:"swing" });
$(this).children("div").animate({width: maxWidth+"px"}, { queue:false, duration:400, easing:"swing"});
lastBlock = this;
}
);
Because the first animation runs slightly before the second, it causes the overall width to become momentarily unequal, which looks a bit funky.
There was a recent disussion about this exact topic on the jQuery dev list. They created a few test cases you might wanna look at. Specially the Johns test.
Here's the discussion topic btw.
The trick is to have a single interval/callback in which all elements are updated.
You can find an example in my post here:
Can I implement a callback with each animation step in jQuery?
What you end up is basically:
var el1 = $("#element1");
var el2 = $("#element2");
var animation = new AnimationTimeline( {
easing: "swing"
, onstep: function( stepValue, animprops )
{
// This is called for every animation frame. Set the elements:
el1.css( { left: ..., top: ... } );
el2.css( { left: ..., top: ... } );
}
});
// And start it.
animation.start();

Categories

Resources