Ok, so I've made a timer that makes parts of my SVG map fadeOut as they cross certain thresholds. However, I want to mess with other parts of the CSS.
I looked at this post, but couldn't make sense of it in terms of my problem.
** Edits Below**
Thanks for the help, I took a look at my code and tried to clean out some of the stuff that didn't need to be there. I also restructured my if statement, putting it inside of the JQuery code. I tried the suggestion below, assigning the var timer outside the interval function, but then my start button no longer worked and the script started running on page load. So, I moved it back to keep things working.
Also, put my code into JSFiddle, but I couldn't get it to work correctly. Will spend some more time familiarizing myself with that in the meantime. Thank you for introducing me to that.
As for my original question:
the .animate() tag works so long as I set it to change the opacity attribute, but has no effect on the other attributes I want to change. I know SVG and CSS have different attribute names, and I've tried both types of names. Here is my code below. I am trying to get the .animate() effect to change the fill color and stroke-width.
var i,timer;
i = 2013;
function start() {
timer = self.setInterval("increment()", 800 )
}
function increment() {
i++;
document.getElementById("timer_out").innerHTML = i ;
$(document).ready( function() {
if (i == 2014) {
$('#AL').animate( {
opacity: 0.3 } , 500 );
}
});
}
function stop() {
clearInterval(timer);
timer = null;
}
function reset() {
stop();
i=2013;
document.getElementById("timer_out").innerHTML = i;
}
I'm really just concerned with the JQuery statement, which works perfectly fine until I replace opacity with a different CSS attribute.
Thanks again for the attention and advice.
1) if you divide any number by 1 you get the original number, your divisions are doing nothing as far as i can tell.
2) setInterval should be written:
timer = setInterval(increment, ( 1000 / divide ))
also note increment() and start() are not good name choices to have in global scope, how many people will think of those names, use anonymous functions maybe to contain scope
(function()
{
// function is now contained within anonymous function scope and not accessible outside
function increment(){}
})()
3) logically step though your code in your head. your code wont work
4) create a fiddle of what you have done so far
Related
I am making a simple JS program and am having some trouble. You can view it here
http://codepen.io/TheAndersMan/pen/mOGVEy?editors=0010
Enter in your name and press enter, it will animate your name, but the letters disappear after the animation, which is understandable. what I don't understand is why my setTimeout isn't working and making them re-appear.
So here is the basic problem:
var timeOut = (a / 2 + 1) * 1000;
document.querySelector(".spanWrap").style.width = char.length * 60 + "px";
setTimeout(function() {
thang.style.opacity = "1"
thang.style.marginTop = "0";
}, timeOut);
So hopefully that is all the info you will need, if not reference my pen, this is all in a for loop and if you see undefined variables here, they are defined in my pen.
So if someone can tell me what I did wrong that would be great.
Thanks in advance!
You have the infamous closure bug.
I noticed that you are transpiring using Babel. Using let instead of var for your variables local to your loop should fix the issue. Notice that in your broken CodePen, the last letter stays while the rest disappear. That is because your thang is always equal to the last letter by the time the timeout handlers execute (the loop has concluded long before).
See http://codepen.io/anon/pen/ObaVyb.
Also, a better idea might be to take a look at animation-fill-mode: forwards, which allows you to retain styles after animations have been run.
Finally, for those of you not using ES6, this code will allow you to achieve the same functionality without creating another wrapper function. (Essentially, setTimeout allows you to pass arguments to your callback when you register each handler.)
setTimeout(function (thang) {
thang.style.opacity = "1"
thang.style.marginTop = "0";
}, timeOut, thang);
The problem is, that you have several timeouts in for loop, that needs references to thang variables, but when your timeouts will be executed thang variable will be equal to the last thang in the cycle, so all the timeout would have the same reference. Hope it's clear.
So, to fix that, you need to bind your timeouts with thangs variables, one by one.
For example, you can do it with closures:
(function(thang) {setTimeout(function() {
thang.style.opacity = "1"
thang.style.marginTop = "0";
}, timeOut);})(thang)
So far I have a little script that detects the scroll top position and at a set level I want it to trigger a jquery counter. So far I have an array with the maximum number inside var = eightyS = [3]; then there is..
if (y > 630) {
$('.targetS').each(function() {
//counter
delay(1000);
});
} else {
return false;
}
Now I've made something similar in C++ years ago (couldn't do it now with a gun to my head) so I followed a similar logic. But this is where I'm stuck. The idea behind this function is that it will do a read out on screen of 0 then 1 then 2 then 3. Any help is greatly appreciated
You could use a setInterval() which executes a function ever second such as below:
var count = 0;
var interval = setInterval(function(){
count++;
$('#counter').text(count);
}, 1000);
I've created a quick JSFiddle
You should be able to wrap this in to your code fairly easily. You may also want to use clearInterval(interval) to stop the function executing when you scroll back up the page; or when you get in to your else block, which would have the same effect. I've added a clearInterval() example to the JSFiddle on click of the stop link. You'll need to make sure the interval variable is in scope when clearing it.
i saw a tutorial in tympanus and i did some changes to look more like a billboard but something is wrong and i don't know what it is! and it's really makes me crazy that where the hell is problem!
the first time that you run it's exactly that i want but when time passes it's getting ugly!i did this modification:
$(function() {
$('#ad_1 > img').each(function(i,e){
rotate($(this),500,3000,i);
});
function rotate(elem1,speed,timeout,i){
elem1.animate({'marginLeft':'18px','width':'0px'},speed,function(){
var other;
if(elem1.parent().attr('id') == 'ad_1')
other = $('#ad_2').children('img').eq(i);
else
other = $('#ad_1').children('img').eq(i);
other.animate({'marginLeft':'0px','width':'35px'},speed,function(){
var f = function() { rotate(other,speed,timeout,i) };
setTimeout(f,timeout+i*100);
});
});
}});
all the rest is just like the tympanus
thank you!!
In the future it will be helpful for you to describe what you are hoping to achieve rather than leaving it to the people of whom you are asking for help to figure it out for themselves. With some fiddling, I determined that what you want is, instead of each panel animating at the same time, a slight delay of the animations from left to right, so that each panel begins animating after its left neighbor has begun its animation.
You attempted to achieve this by adding an increment to the duration between a panel's rotations. The increment, computed as a function of the panel's index, is larger for higher indexes. The problem with this approach is that each panel spends a different duration of time in its display state - so as time goes on, the whole image becomes increasingly mangled.
The panels all need to have the same display duration, so revert your change to the setTimeout.
setTimeout(f, timeout);
What you actually want to do is to delay when each panel starts rotating. This can be achieved by adding a setTimeout in the each handler that initiates the rotations:
$('#ad_1 > img').each(function (i, e) {
setTimeout($.proxy(function () {
rotate($(this), 500, 7000, i);
}, this), (i * 100));
});
You will notice that I have increased the timeout value passed to rotate because more time will be required to accommodate the sequential animations.
I would also recommend that you put some effort into better formatting your code. Your sample, due to poor indentation, lack of spacing, and omitted curly braces, makes reading it a chore.
It's hard to tell without looking at the rest of the code, but your else statement is missing brackets. I think you meant to do this:
$(function() {
$('#ad_1 > img').each(function(i,e){
rotate($(this),500,3000,i);
});
function rotate(elem1,speed,timeout,i){
elem1.animate({'marginLeft':'18px','width':'0px'},speed,function(){
var other;
if(elem1.parent().attr('id') == 'ad_1') {
other = $('#ad_2').children('img').eq(i);
} else {
other = $('#ad_1').children('img').eq(i);
other.animate({'marginLeft':'0px','width':'35px'},speed,function(){
var f = function() { rotate(other,speed,timeout,i) };
setTimeout(f,timeout+i*100);
});
}
});
}});
*edit: Did you remember to include jQuery?
<script src="jquery-1.3.2.js" type="text/javascript"></script>
I'm learning javascript for fun, and am having a weird problem. I'm trying to create my own fade-in function. However, my code doesn't work, it simply shows the "content" div in full opacity.
The setContentOpacity function does work, I've tested it by itself and it works like a charm.
Ideally what I think should be happening is that 1000 "setTimeout" calls should be placed on the "stack", with the first one setting opacity low with no timeout, the second one setting opacity a little higher with a small timeout, all the way to the last call which sets opacity to 1000 with 3000 timout.
So basically, it should be setting opacity to 0 right away, to ~333 in 1 second, to ~666 in 2 seconds, and to 1000 in 3 seconds. I think my logic is sound here; the calls to setting opacity should resolve in a manner over time that creates a fade in effect.
So here's the relevent code:
<script language='JavaScript' type='text/JavaScript'>
//takes a value from 0-1000
function setContentOpacity(value) {
document.getElementById('content').style.opacity = value/1000;
document.getElementById('content').style.filter = 'alpha(opacity=' + value/10 + ')';
}
function fadeInContent(){
setContentOpacity(0);
for (var i=0;i<=1000;i++)
{
setTimeout(function(){setContentOpacity(i);}, (i*3));
}
}
onload=fadeInContent;
</script>
(note: I tried calling simply setTimeout(setContentOpacity(i), (i*3));, but it didn't seem to work, and I got slightly better results using the anonymous function)
Any idea what's wrong here? Thanks in advance!
You need to capture the value of i when assigning to setTimeout.
Try this
for (var i=0;i<=1000;i++)
{
(function(ind) {
setTimeout(function(){setContentOpacity(ind);}, (ind*3));
})(i);
}
As you know the scope of a variable is function scoped. And the same value of i is shared by all the callbacks of setTimeout. So the value of i will be 1000 . So looks as if it had no effect, this is because the value of the variable scoped will always be the last iteration as it is shared by the same common scope. . By enclosing it in Immediately Invoked Function Expression you are creating a new function with the value of i scoped to it.
Check Fiddle
I think the major issue here is that you're creating a 1000 setTimeout callbacks. An alternative, if you wanted to run something every x seconds would be setInterval.
var i = 0;
var refreshIntervalId = window.setInterval(function(){
setContentOpacity( i * 3 );
i++;
if( i > 1000 ) {
clearInterval( refreshIntervalId );
}
}, 1000);
It will run once a second (1000ms), calling your opacity function each time until it hits a 1000, then turns off again.
Scenario:
I want to create a jQuery controllable jackpot "spinner" that will rapidly sequence a number of random images through a div before settling on one, with the delay interval between each equal but changeable. For mockup purposes, I'm simply changing CSS color classes to a box, although in the final I'll use background images.
I thought this would be a no-brainer to do with a loop. I'm sure there's a more efficient way to do this, but guessed the below would work fine. However, I discovered I have no way to control the CSS color swap speed. This whips through the color class changes instantly and just shows the last one. What I'd like is a delay where indicated.
jQuery delay() doesn't seem to work when chained with addClass(), though it works fine with effects. So I tried using window.setTimeout, but as far as I can see, in this context it requires a kludgey function call. The code as written below executes all the function calls after the loop has run. Is this a closure issue? Don't want to use setInterval because these will be limited iterations.
Thanks for any advice!
for (var j= 9; j >= 0; j--) {
$('#box1').attr('class', 'boxes'); // strips all current classes, replaces them with class 'boxes', which has general CSS characteristics
var numRand = Math.floor(Math.random() * 6);
var randomClass = colorArray1[numRand]; // pull random class from an array of six choices
$('#box1').addClass(randomClass);
// Everything above here works fine, would like loop delay here
// Tried using straight-up setTimeout -- doesn't appear to like loops
window.setTimeout(outerFunc, 1000);
};
function outerFunc() {
alert('nobody here but us chickens!');
};
If you want to use .delay() with a method like .addClass(), you can add it to the queue with jQuery's .queue() method.
$('#box1').delay(1000)
.queue(function( nxt ) {
$(this).addClass(randomClass);
nxt(); // allow the queue to continue
});
Otherwise, if I get what you want, you could multiply the 1000 ms for the setTimeout() by the current value of j, so that each time the duration increases.
window.setTimeout(outerFunc, (1000 * j));
setTimeout and setInterval work differently in javascript to the way you want to use them.
Both functions take the function that you pass in and attach them to the window DOM object. Then, after the delay you have passed in has passed, and when there is no other script currently running, they get called from the window object.
To get the functionality you are after, you will need to convert your code so that the jQuery addclass call is inside the function you are passing to setTimeout.
Perhaps recursion would work?
// this code is not tested
var j = 9;
function myFunc() {
// code here
j--;
if(j >= 0) setInterval(myFunc, 1000);
}
I haven't used the queue class in jQuery myself (first I've heard of it, but it sounds cool). That might be the better answer, but this should be a decent alternative if the queue doesn't work as expected.
UPDATE: I just noticed that in your code it looks like you are expecting setTimeout to work like Thread.Sleep in .Net. setTimeout doesn't work that way. It works more like Thread.Start where your code continues on as soon as you call it.