Pretty specific one this time, I have the following code to loop some fades depending on conditions, as you can see depending on the state the animation differs slightly.
At the moment it is producing the effect I want but it seem's to slow down gradually until at around 3 minutes it stops completely.
I've gotten to the point where I can't stare at it any longer! can anyone offer me some advice on how to make this a continuous loop?
Here's a fiddle: http://jsfiddle.net/CbNc5/
var glimmerLen = 16;
var initiated = false;
var animateLoop = false;
var timeout;
function glimmerAnimate() {
if (!initiated) {
timeout = window.setTimeout(function() {glimmerAnimate();}, 2500);
initiated = true;
} else if (!animateLoop && initiated) {
$("#glimmer li").fadeTo(1500, 0.5, function(){
glimmerAnimate();
animateLoop = true;
});
} else if (animateLoop) {
var rangeMax = glimmerLen + 1;
var randObj = Math.floor(Math.random() * rangeMax);
$("#glimmer-" + randObj).fadeTo(1500, 0.8, function() {
$("#glimmer-" + randObj).fadeTo(2000, 0.2);
glimmerAnimate();
});
}
}
I have rewrite this, hope this help (http://jsfiddle.net/CbNc5/5/)
function fadeLoop(e) {
$(e).fadeTo(Math.random() * 500, 0.2, function () {
$(this).fadeTo(Math.random() * 500, 1, function () {
fadeLoop(this);
});
});
}
$('li').each(function () {
fadeLoop(this);
});
P.S. If you only want loop opacity, you can use CSS3, it will be more simple
Related
Basically I'm trying to make a skull flicker over a persons face, I've achieved it flashing up once. But the effect I'm trying to achieve is that it looks more organic and random. Here's the basic structure:
function flicker() {
var maxFlick = 6,
amount = Math.round(Math.random() * maxFlick),
running = false;
function showHide() {
$flicker.show();
running = true;
setTimeout(function() {
$flicker.hide();
running = false;
}, 100)
}
for (i = 0; i < amount; i++) {
if(!running) {
showHide();
}
}
}
setInterval(flicker, 4000);
I had presumed that running a for loop with a random amount statement would produce the desired effect, but it's still only flashing up once every 4000milliseconds as previously. Any pointers?
With the help of Regent and this fiddle I came up with the answer:
function flicker() {
var maxFlick = 6,
amount = Math.round(Math.random() * maxFlick),
delta = 2,
timer;
var doneFlicks = 0;
var flickInterval = setInterval(showHide, timer);
function showHide() {
timer = Math.round((Math.random() + delta) * 100)
$flicker.show();
var hide = setTimeout(function() {
$flicker.hide();
doneFlicks++
}, 20)
if (doneFlicks == amount) {
clearInterval(flickInterval);
}
}
}
setInterval(flicker, 3000);
This produces a randomised flicker effect that's called every 3 seconds - perfect for a horror film effect!
Thanks again to Regent for all the help!
I'm developing an HTML5 application and I'm drawing a sequence of images on the canvas with a certain speed and a certain timeout between every animation.
Able to use it multiple times I've made a function for it.
var imgNumber = 0;
var lastImgNumber = 0;
var animationDone = true;
function startUpAnimation(context, imageArray, x, y, timeOut, refreshFreq) {
if (lastImgNumber == 0) lastImgNumber = imageArray.length-1;
if (animationDone) {
animationDone = false;
setTimeout(playAnimationSequence, timeOut, refreshFreq);
}
context.drawImage(imageArray[imgNumber], x, y);
}
function playAnimationSequence(interval) {
var timer = setInterval(function () {
if (imgNumber >= lastImgNumber) {
imgNumber = 0;
clearInterval(timer);
animationDone = true;
} else imgNumber++;
}, interval);
}
Now in my main code, every time startUpAnimation with the right parameters it works just fine. But when I want to draw multiple animations on the screen at the same time with each of them at a different interval and speed it doesnt work!
startUpAnimation(context, world.mushrooms, canvas.width / 3, canvas.height - (canvas.height / 5.3), 5000, 300);
startUpAnimation(context, world.clouds, 100, 200, 3000, 100);
It now displays both animations at the right location but they animate both at the interval and timeout of the first one called, so in my case 5000 timeout and 300 interval.
How do I fix this so that they all play independently? I think I need to make it a class or something but I have no idea how to fix this. In some cases I even need to display maybe 5 animations at the same time with this function.
Any help would be appreciated!
try something like this
var Class = function () {
this.imgNumber = 0;
this.lastImgNumber = 0;
this.animationDone = true;
}
Class.prototype.startUpAnimation = function(context, imageArray, x, y, timeOut, refreshFreq) {
// if (lastImgNumber == 0) lastImgNumber = imageArray.length-1;
if (this.animationDone) {
this.animationDone = false;
setTimeout(this.playAnimationSequence, timeOut, refreshFreq, this);
}
// context.drawImage(imageArray[imgNumber], x, y);
};
Class.prototype.playAnimationSequence = function (interval, object) {
var that = object; // to avoid flobal this in below function
var timer = setInterval(function () {
if (that.imgNumber >= that.lastImgNumber) {
that.imgNumber = 0;
clearInterval(timer);
that.animationDone = true;
console.log("xxx"+interval);
} else that.imgNumber++;
}, interval);
};
var d = new Class();
var d1 = new Class();
d.startUpAnimation(null, [], 300, 300, 5000, 50);
d1.startUpAnimation(null,[], 100, 200, 3000, 60);
It should work,
As far as I can see, each call to startUpAnimation will draw immediately to the canvas because this execution (your drawImage(..) call) hasn't been included in the callback of the setTimeout or setInterval.
The aim: to write a js (using jquery) that will perform 2 blinking of the row.
What I currently have is
var $second_row = $('table tr:eq(1)'),
target_color = 'PaleGreen',
original_color = $second_row.css('background-color');
$second_row.css('background-color', target_color);
scheduleOriginalColor();
function scheduleTargetColor() {
setTimeout(function() {
$second_row.css('background-color', target_color);
scheduleOriginalColor(true);
}, 500);
}
function scheduleOriginalColor(stop) {
setTimeout(function() {
$second_row.css('background-color', original_color);
if (!stop) {
scheduleTargetColor();
}
}, 500);
}
http://jsfiddle.net/zerkms/ecfMU/1/
But it looks ugly and I'm sure there is a better way of writing the same.
Any proposals?
UPD: there is my second attempt, a bit more clear: http://jsfiddle.net/zerkms/ecfMU/2/
var $second_row = $('table tr:eq(1)'),
target_color = 'PaleGreen',
original_color = $second_row.css('background-color');
setRowColor(target_color, 500);
setRowColor(original_color, 1000);
setRowColor(target_color, 1500);
setRowColor(original_color, 2000);
function setRowColor(color, timing) {
setTimeout(function() {
$second_row.css('background-color', color);
}, timing);
}
Try this, using toggleClass and a background color:
var blink = setInterval(function() {
$('table tr:eq(1)').toggleClass('highlight');
}, 500);
setTimeout(function() {
clearInterval(blink);
}, 2100); // run 4 times, added a little padding time just in case
.highlight {
background-color:PaleGreen;
}
Demo: http://jsfiddle.net/ecfMU/10/
The following lets you define the element, color, number of flashes, and speed. Another added benefit is that it doesn't require any of the bloat of jQuery. Always favor raw JavaScript when you can.
function flashBG( e, c, x, z ) {
var d = e.style.backgroundColor, i = 0, f = setInterval(function(){
e.style.backgroundColor = ( e.style.backgroundColor == d ) ? c : d ;
++i == ( x * 2 ) && clearInterval( f );
}, z );
}
Call it like this:
flashBG( document.body, "PaleGreen", 2, 500 );
Demo: http://jsbin.com/axuxiy/3/edit
For readability, the following may be more educational:
function flashBG( element, color, flashes, speed ) {
var original = element.style.backgroundColor;
var counter = 0;
var interval = setInterval(
function() {
if ( original === element.style.backgroundColor ) {
element.style.backgroundColor = color;
} else {
element.style.backgroundColor = original;
}
if ( ++counter == ( flashes * 2 ) ) {
clearInterval( interval );
}
}, speed );
}
Javascript isn't my forte - so I may get a bit of the syntax wrong.
EDIT: Demonstration
EDIT #2: Easily extensible - rainbow version
However... a very simple way of doing it is have the colors in an array, and an int var with an index. Then have only one scheduled function, like this:
//Somewhere else we have:
//var colorArray = blah... blah.. blahh, it has values [palegreen,regularwhite]
//blah blah scheduleColor(0);
//var numBlinks = 2;
//then for your scheduler
function scheduleColor(ind) {
$second_row.css('background-color', colorArray[ind % colorArray.length]);
if (ind < (colorArray.length * numBlinks) - 1) {
setTimeout(function() {
scheduleColor(ind + 1);
}, 500);
}
}
The basic idea is rather than two schedulers, you have one, that iterates. As a plus, you can easily set it to blink any number of times you want, or cycle through multiple colors.
Heck, if you wanted, you could have it cycle through the rainbow.
Edited for some syntax/corrections.
My answer for you is a portmanteau of Wesley's and Ricardo's answers, so I can't take much credit for it. I'm .delay() and .queue() along with .toggleClass(). I think it ends up a nice bit of code.
Some CSS:
.highlight {
background-color:PaleGreen;
}
And the JS:
var $second_row = $('table tr:eq(1)');
function blink(el) {
el.addClass('highlight');
for(i=0; i<3; i++) {
el.delay(500).queue(function() {
$(this).toggleClass('highlight');
$(this).dequeue();
});
}
}
blink($second_row);
The Fiddle
var $second_row = $('table tr:eq(1)'),
target_color = 'PaleGreen',
original_color = $second_row.css('background-color');
$second_row.css('background-color', target_color).delay(500).queue(function(){
jQuery(this).css('background-color', original_color);
});
Working : Fiddle
Can you add jQuery UI?
If so, you can animate the background for a smoother transition.
http://jsfiddle.net/ecfMU/18/
I'm using this code to make my logo flicker on my website. But It becomes annoying when it continues to flicker while browsing, how can I set a time to allow it to flicker for something like the first 15seconds on page load, then stops?
JS code I'm using:
$(document).ready(
function(){
var t;
const fparam = 100;
const uparam = 100;
window.flickr = function(){
if(Math.round(Math.random())){
$("#logodcoi").css("visibility","hidden");
t = setTimeout('window.unflickr()',uparam);
}
else
t = setTimeout('window.flickr()',fparam);
}
window.unflickr = function(){
if(Math.round(Math.random())){
$("#logodcoi").css("visibility","visible");
t = setTimeout('window.flickr()',fparam);
}
else
t = setTimeout('window.unflickr()',uparam);
}
t = setTimeout('window.flickr()',fparam);
});
You could have a counter, which you then use to decide whether you want to set another timeout. As a side note, you should never add functions to window and then passing a string to setTimeout. Always just pass the function itself:
$(document).ready(function(){
var t;
var amount = 0;
const fparam = 100;
const uparam = 100;
function timeout(f, t) { // this function delegates setTimeout
if(amount++ < 150) { // and checks the amount already (un)flickered
setTimeout(f, t); // (150 * 100 ms = 15 s)
}
}
var flickr = function(){
if(Math.round(Math.random())){
$("#logodcoi").css("visibility","hidden");
t = timeout(unflickr,uparam);
}
else
t = timeout(flickr,fparam);
};
var unflickr = function(){
if(Math.round(Math.random())){
$("#logodcoi").css("visibility","visible");
t = timeout(flickr,fparam);
}
else
t = timeout(unflickr,uparam);
};
t = timeout(flickr,fparam);
});
I see you're using jquery, you could use the following, if I remember correctly, all the stuff I use below has been in jquery since 1.0, so you should be good:
counter = 1;
function hideOrShow(){
$(".classToSelect").animate({"opacity": "toggle"}, 100);
counter = counter +1;
if (counter >= 21) clearInterval(flickerInterval);
}
flickerInterval = setInterval(hideOrShow, 100);
Change the selector, animation duration, and variable names to whatever you fancy/need.
I have a bug in Javascript where I am animating the margin left property of a parent container to show its child divs in a sort of next/previous fashion. Problem is if clicking 'next' at a high frequency the if statement seems to be ignored (i.e. only works if click, wait for animation, then click again) :
if (marLeft === (-combinedWidth + (regWidth) + "px")) {
//roll margin back to 0
}
An example can be seen on jsFiddle - http://jsfiddle.net/ZQg5V/
Any help would be appreciated.
Try the below code which will basically check if the container is being animated just return from the function.
Working demo
$next.click(function (e) {
e.preventDefault();
if($contain.is(":animated")){
return;
}
var marLeft = $contain.css('margin-left'),
$this = $(this);
if (marLeft === (-combinedWidth + (regWidth) + "px")) {
$contain.animate({
marginLeft: 0
}, function () {
$back.fadeOut('fast');
});
} else {
$back.fadeIn(function () {
$contain.animate({
marginLeft: "-=" + regWidth + "px"
});
});
}
if (marLeft > -combinedWidth) {
$contain.animate({
marginLeft: 0
});
}
});
Sometimes is better if you create a function to take care of the animation, instead of writting animation code on every event handler (next, back). Also, users won't have to wait for the animation to finish in order to go the nth page/box.
Maybe this will help you:
if (jQuery) {
var $next = $(".next"),
$back = $(".back"),
$box = $(".box"),
regWidth = $box.width(),
$contain = $(".wrap")
len = $box.length;
var combinedWidth = regWidth*len;
$contain.width(combinedWidth);
var currentBox = 0; // Keeps track of current box
var goTo = function(n) {
$contain.animate({
marginLeft: -n*regWidth
}, {
queue: false, // We don't want animations to queue
duration: 600
});
if (n == 0) $back.fadeOut('fast');
else $back.fadeIn('fast');
currentBox = n;
};
$next.click(function(e) {
e.preventDefault();
var go = currentBox + 1;
if (go >= len) go = 0; // Index based, instead of margin based...
goTo(go);
});
$back.click(function(e) {
e.preventDefault();
var go = currentBox - 1;
if (go <= 0) go = 0; //In case back is pressed while fading...
goTo(go);
});
}
Here's an updated version of your jsFiddle: http://jsfiddle.net/victmo/ZQg5V/5/
Cheers!
Use a variable to track if the animation is taking place. Pseudocode:
var animating = false;
function myAnimation() {
if (animating) return;
animating = true;
$(this).animate({what:'ever'}, function() {
animating = false;
});
}
Crude, but it should give you the idea.
Edit: Your current code works fine for me as well, even if I jam out on the button. On firefox.