I`m having a troubble with a simple thing.
I have an div, when clicked, an amination start (an infinite loop of images changing, simulating an animated gif).
But, when i click on the other div, the first one need to stop, and start just the other animation, and this goes on to every animation (will be 8 on total).
Here is the code for just one image loop:
var t1;
var t2;
var anim1 = new Array ('img/testes2/anim1_1.png','img/testes2/anim1_2.png');
var anim2 = new Array ('img/testes2/anim2_1.png','img/testes2/anim2_2.png');
var index = 1;
var verifica1 = 0;
var verifica2 = 0;
function rotateImage1(){
$('#imagemPrinc').fadeOut(0, function(){
$(this).attr('src', anim1[index]);
$(this).fadeIn(0, function(){
if (index == anim1.length-1){
index = 0;
}
else{
index++;
}
});
});
return false;
}
function stopTimer1(){
if(verifica1 = 1){
clearInterval(t2);
}
}
function muda1(){
if (verifica1 = 1){
//stopTimer2();
//$('#bgImagem').css({'background-image':'url(img/testes2/anim1_1.png)'});
t1 = setInterval(rotateImage1,500);
}
}
The same function for the second animation.
The verifica var, and the stopTimer function, i tried to make one stop, and just the other plays, but doesn't seems to be working. That's why it's commented on the code.
It will be easier to look the code running, so thats it ---HERE---
The clickable divs are those two Red Squares.
Someone can help me please!?
Thanks!
clearTimeout takes as argument the timer id returned by the setInterval function (here it's t1).
Instead of using fadeOut and fadeIn with a duration of 0, you should simply use hide and show.
As an aside, you can simplify this block :
if (index == anim1.length-1){
index = 0;
}
else{
index++;
}
in
index = [(index+1)%anim1.length];
And this is very wrong :
if(verifica1 = 1){
This is not a test : it always change verifica1 and is always true. You probably want ==.
Is there a point in your code where you (voluntarily) set verifica1 ?
Related
I have this function running on a mousemove event. The functionality is to iterate a list of images and move to the top (z-index) each one at a time. This is working right but my problem is that the script is running really fast and the images displays really fast. How can I add a delay to the function or the event? I tried with setTimeOut with no positive effects
Here's the code
// creating variables
const imgQty = 6;
const holder = document.getElementById('holder')
var counter = 1;
var isMoving = false;
var bgtimeout, imgtimeout;
var bkgImgs = []
// this creates the containers for each img
for (let i = 1; i <= imgQty; i++) {
var newDiv = document.createElement('div');
newDiv.classList.add('background')
newDiv.classList.add(`background--${i}`)
newDiv.setAttribute("style", `background-image: url('imgs/${i}.jpg'); z-index: 0;`);
holder.appendChild(newDiv);
bkgImgs.push(newDiv)
}
//this moves the counter and also hides the images when the mouse is not moving
function changeBkg(e){
counter >= imgQty ? counter = 1 : counter++
holder.classList.add('isActive')
clearTimeout(bgtimeout);
clearTimeout(imgtimeout);
bgtimeout = setTimeout(function(){holder.classList.remove('isActive')}, 150);
moveImgs();
}
// and here is where my issue is, this function is working but not as I expected
function moveImgs(){
for(var i = 0; i < bkgImgs.length; i++){
if(bkgImgs[i].classList.contains(`background--${counter}`)){
bkgImgs[i].style.zIndex = "1";
} else{
bkgImgs[i].style.zIndex = "0";
}
}
}
Is my logic right? or do I have to rethink the code?
the event is fired in the section:
<section class="main" onmousemove="changeBkg(event)"></section>
Use Debounce
Something like this should work (remove the timeout from inside changeBkg):
//change 300ms to suite your needs
<section class="main" onmousemove="debounce(changeBkg(event),300)"></section>
A debounce is a higher-order function, which is a function that returns another function. This is done to form a closure around the func , wait , and immediate function parameters and the timeout variable so that their values are preserved.
Further reading/if you prefer to implement yourself: Debounce Article
It has been resolved.
As what I needed was some sort of animation I figured it out using greensock
So my event have inside this animation that triggers when animPlay is true and when is playing remains false
if(animPlay){
animPlay = false
var tl = new TimelineMax();
tl.staggerFromTo(bkgImgs, .5, {zIndex:0}, {zIndex:1}, .15, 0)
.set(bkgImgs, {zIndex:0, onComplete:() => animPlay = true}, '+=0' )
}
I am making an info screen, and for that, it needs to show reviews from their customers pulled from Trustpilot.
I got the reviews and everything formatted in HTML showing the 20 latest, but I want to present it very sweet. I am not a JavaScript guru, but I thought i would do it using jQuery and its fadein function.
What is want, is have 20 unique divs fading in with X milliseconds difference popping randomly up. By unique I mean, that each div must have unique content. And by randomly popping up, I mean that if box 1 spawns first, then the next should be 5, then 14 etc, and then another cycle the next time around.
Just like what I made here;
$(function() {
var box = $('.box');
var delay = 100;
for (i = 0; i < 30; i++) {
setTimeout(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}
});
http://jsfiddle.net/CCawh/5/
Is this even possible, and how would this be done?
I am very new to JavaScript, so please bear with me if I ask to much
Thanks in advance.
EDIT:
The HTML i want to spawn will all be wrapped in divs, so it would go like this;
<div id="one">content</div>
<div id="two">content</div>
<div id="three">content</div>
<div id="four">content</div>
etc.
Made up a nice function for you. I believe this may be what you are looking for
Here's a rundown of how it works :
Populate an array with numbers randomly generated 1-10 in this case.
Run through that array with a set interval, and when everything has
been added stop the interval
pretty straightforward from there. Set the visibility etc. You should be able to change up the function to dynamically add HTML elements and what-not, but just giving you something to start with.
var usedNum = [];
var i, j, y;
i = 0;
for(y = 0; y < 10; y++){
var x = Math.floor((Math.random() * 10) + 1);
if(!isUsed(x)) usedNum.push(x);
else y--;
}
var showInterval = setInterval ( function(){
if(i == 10){
clearInterval(showInterval);
}
$(".container div[data-line='" + usedNum[i] + "']").css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0});
i++;
}, 500);
function isUsed(num) {
var used = false;
for(j = 0; j < usedNum.length; j++){
if(usedNum[j] == num){
used = true;
}
}
return used;
}
Demo fiddle : http://jsfiddle.net/xS39F/3/
Edit:
You can also mess around with the speed of the animation. In this demo (http://jsfiddle.net/adjit/XYU34/1/) I set the speed to 1000 so the next element starts fading in before the last element was done fading in. Makes it look a little smoother.
Instead of using a for loop and setTimeout, would setInterval work better for what you need? Some HTML might help better understand what you're trying to achieve.
$(function() {
var box = $('.box');
var delay = 100;
var interval = setInterval(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}, delay);
});
<script src = "http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script>
$(document).ready(function(){
var secs_time;
var timer2;
var arrayseq1 = [];
var secs_up = 0;
var timer1;
var secs_down = 0;
$("#pad").mousedown(function(){
$(this).css("background-color", "lightgrey");
clearInterval(timer2);
timer1 = setInterval(function(){
secs_down = secs_down + 1;
$("#pad").html(secs_down);
},1);
arrayseq1 = arrayseq1.concat([secs_down]);
}).mouseup(function(){
$(this).css("background-color", "grey");
clearInterval(timer1);
timer2 = setInterval(function(){
secs_up = secs_up + 1;
$("#pad").html(secs_up);
},1);
arrayseq1 = arrayseq1.concat([secs_up]);
});
$("#pad").mouseleave(function(){
clearInterval(timer2);
});
$("#done").click(function(){
arrayseq1.splice(1, 1);
arrayseq1.splice(0, 1);
var counter = 0;
var colors = ["#FF3E96", "#4169E1", "#7FFF00","#FF4500","#FF7F00", "black", "white"];
while(counter <= arrayseq1.length){
setTimeout(function(){
var color = colors[Math.floor(Math.random()*colors.length)];
$("body").css("background-color", color);
}, arrayseq1[counter]);
counter++;
}
});
});
</script>
<div style = "height:500px;width:600px;background-color:grey;border-radius:4px;margin:0 auto;margin-top:10%;" id = "pad"></div>
<input type = "button" id = "done" value = "play">
Hi all.
I am making a small program, that when you press, and press of a huge grey button, it records the time its held down, and up and all put into an array (read the code to get a better understanding, its not to hard to understand). Anyway, so it records the times to the array successfully, so the array "arrayseq1" does have a list of times e.g [106,144,114,152,122,161,130,311,148,357]. The problem comes when i try and loop through each number, and use each as a delay for the flash of the background. So, the specific problem is when i substitute "arrayseq1[counter]" in the setTimeout function. For some reason i do not understand, it is undefined. Why? How can i fix this?
in this jsfiddle: http://jsfiddle.net/5V4Lv/
I alert the value arrayseq1[counter] the line before i use it for the setTimeout function, and as you will see, it alerts "undefined"
so you can test this out successfully, click on the grey box fastly and randomly, and then when you are down, move your mouse off the box to stop recording. Then click play to start the flashing.
The original aim of this was for the background to flash in random colours in exact sync and beat to how you initially clicked the grey box.
Thanks!
$(document).ready(function fadeIt() {
$("#cool_content > div").hide();
var sizeLoop = $("#cool_content > div").length;
var startLoop = 0;
$("#cool_content > div").first().eq(startLoop).fadeIn(500);
setInterval(function () {
$("#cool_content > div").eq(startLoop).fadeOut(1000);
if (startLoop == sizeLoop) {
startLoop = 0
} else {
startLoop++;
}
$("#cool_content > div").eq(startLoop).fadeIn(1500);
}, 2000);
});
Here I want a class of divs to animate, infinitely!
However, because the interval is set to two seconds there is period where no div is showing!
What would be an appropriate way to loop the animation of these divs?
I thought about using a for loop but couldn't figure out how to pass a class of divs as arguments. All your help is appreciated.
Thanks!
Ok, generally, you should know that Javascript is a single threaded environment. Along with this, the timer events are generally not on time accurately. I'm not sure how jQuery is doing fadeIn and fadeOut, but if it's not using CSS3 transitions, it's going to be using timeOut and Intervals. So basically, there's a lot of timer's going on.
If you go with the for loop on this one, you'd be blocking the single thread, so that's not the way to go forward. You'd have to do the fade in/out by yourself in the setInterval.
Setting the opacity on each interval call. Like div.css('opacity', (opacity -= 10) + '%')
If you're trying to fade in and out sequentially, I think maybe this code would help
var opacity = 100,
isFadingIn = false;
window.setInterval(function() {
if (isFadingIn) {
opacity += 10;
if (opacity === 100) isFadingIn = false;
} else {
opacity -= 10;
if (opacity === 0) isFadingIn = true;
}
$('#coolContent > div').css('opacity', opacity + '%');
}, 2000);
Consider the following JavaScript / jQuery:
$(function(){
var divs = $('#cool_content > div').hide();
var curDiv;
var counter = 0;
var doUpdate = function(){
// Hide any old div
if (curDiv)
curDiv.fadeOut(1000);
// Show the new div
curDiv = divs.eq(counter);
curDiv.fadeIn(1000);
// Increment the counter
counter = ++counter % divs.length;
};
doUpdate();
setInterval(doUpdate, 2000);
});
This loops infinitely through the divs. It's also more efficient than your code because it only queries the DOM for the list of divs once.
Update: Forked fiddle
instead of
if (startLoop == sizeLoop)
{
startLoop = 0
}
else
{
startLoop++;
}
use
startLoop =(startLoop+1)%sizeLoop;
Check the demo http://jsfiddle.net/JvdU9/ - 1st div is being animated just immediately after 4th disappears.
UPD:
Not sure I've undestood your question, but I'll try to answer :)
It doesn't matter how many divs you are being looped - 4, 5 or 10, since number of frames are being calculated automatically
x=(x+1)%n means that x will never be greater than n-1: x>=0 and x<n.
x=(x+1)%n is just shorten equivalent for
if(x<n-1)
x++;
else
x=0;
as for me first variant is much readable:)
And sorry, I gave you last time wrong demo. Correct one - http://jsfiddle.net/JvdU9/2/
Basically I need the thumbnails to rotate every time the user hovers over an image. Here is my failed attempt:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$('img').hover(function() {
theImage = $(this).attr('id');
otherImages = $(this).attr('class').split('#');
rotateThumbs(otherImages, theImage);
}, function() {
//
});
});
function rotateThumbs(otherImages, theImage) {
for (i=0; i < otherImages.length; i++) {
setInterval($('#'+theImage).attr('src', otherImages[i]), 1000);
}
}
</script>
<img id="myImage" src="http://www.google.com/images/logos/ps_logo2.png" class="http://www.google.com/images/logos/ps_logo2.png#http://l.yimg.com/a/i/ww/met/yahoo_logo_us_061509.png#http://dogandcat.com/images/cat2.jpg" width="174" height="130" />
Does anyone know how this may be accomplished?
Some issues here.
setInterval requires a function reference as it's first argument, but you are executing code that returns a jQuery object.
setInterval executes the first function repeatedly at the specified interval. Is that what you are trying to do? Swap images every second?
Depending on how you correct the first issue, you could run into an issue where i is otherImages.length and thus the src is set to undefined.
Assuming you worked around issue 3, you will have the problem that the image swaps will happen imperceptibly fast and it will appear as though the last image is always displayed.
Instead, don't use a loop. Increment a counter each time a new image is displayed. Try this:
function rotateThumbs(otherImages, theImage) {
var i = 0;
var interval = setInterval(function() {
$('#'+theImage).attr('src', otherImages[i++]);
if (i >= otherImages.length) {
clearInterval(interval);
}
}, 1000);
}
I've implemented a fully-functional example here. This addresses some of the issues that #gilly3 notes, but uses closures instead of an incrementing counter to keep track of the current image:
$(function() {
$('img').hover(function() {
// declaring these variables here will preserve
// the references in the function called by setInterval
var $img = $(this),
imageList = $img.attr('class').split('#'),
intervalId;
// start the cycle
intervalId = window.setInterval(function() {
var next = imageList.pop();
if (next) {
$img.attr('src', next);
} else {
// stop the cycle
intervalId = window.clearInterval(intervalId);
}
}, 1000);
}, function() {});
});
As you can see, using a closure is much easier when you declare the function passed to setInterval inline, rather than as a separate, named function. You could still have a rotateThumbs function if you wanted, but you might need to do some more work to ensure that the variables were being passed properly.
Edit: I made an updated version that continues to cycle as long as the mouse is hovering.
I have adjusted the answer for Sam, taking pre-loading the image into account, so that you won't have a possible deplay at the first rotation.
function rotateThumbs(otherImages, theImage) {
if(!$('#'+theImage).data('setup')){
$('#'+theImage).data('setup', true); // do not double pre-loading images
var $body = $('body');
for(var j = 0; j < otherImages.length; j++){
$body.append($('<img/>').attr('src', otherImages[j])
.css('display', 'none'));
}
}
var i= 0;
setInterval(function(){
$('#'+theImage).attr('src', otherImages[i++]);
if(i >= otherImages.length){i = 0}
}, 1000);
}