I'm trying to create a fading effect using vanilla.js instead of jQuery. I'm using the following code to create the hide and show effect:
document.getElementById("pic-num-submit").onclick = function() {
fade();
};
var home = document.getElementById('home').style;
home.opacity = 1;
var agree = document.getElementById('agree').style;
agree.opacity = 0;
agree.display = "none";
function fade() {
if((home.opacity -= .1) < 0) {
home.display = "none";
show();
}
else {
setTimeout(fade, 40);
}
}
function show() {
if((agree.opacity += 0.2) < 1) {
agree.display = "";
}
else {
setTimeout(show, 40);
}
}
Everything is working with the fade function (in Firefox) But when I invoke the show function it only runs once, then it removes the display styling, and shows the div element at 0.2 opacity. I'm not sure what I'm doing wrong.
Here is a jsFiddle example of the problem I am having: http://jsfiddle.net/L54Aw/2/
Also it's broken in Chrome for some reason (The fade function never completes because of something to do with a js decimal subtracting problem)
Your "show" function is not correct. You only set up the timer when the opacity is not less than one. Initially, it is, so the code only runs once.
You're also running into a weirdness in JavaScript that pertains to a significant difference between the + and - operators. Subtraction is always numeric, but not so addition!
Here's a working "show" function:
function show() {
agree.display = ""; // only need this the first time anyway
agree.opacity = +(agree.opacity) + 0.2;
if (agree.opacity <= 1)
setTimeout(show, 40);
}
That unary + operator forces the "opacity" property to be interpreted as a number. Without that, it's a string! Thus adding 0.2 to the string "0.2" gives you "0.20.2", which is nonsense.
The decrementing you did for the other element worked OK because the subtraction operator coerces operands to numbers.
I can't comment on Pointy's solution, but here's what you could do with the fade function to avoid the bug that happens when you subtract low numbers:
function fade() {
home.opacity -= .05;
if(home.opacity - .05 < 0) {
home.display = "none";
show();
}
else {
setTimeout(fade, 20);
}
}
It isn't bulletproof, but it works by subtracting .05 instead of .1 and counter it by doubling the speed of the animation.
you probably want
(agree.opacity += 0.2) > 1
instead of
(agree.opacity += 0.2) < 1
Related
I have this code where if the opacity is less than or equal to 0, the message number is suppose to go up by 1, but when I run the code, the message number increases by 77 or 152 or 66, etc. Could you help me?
My code:
//variables
var x = 0;
var opacity = 0;
var messageNumber = 0;
var talk1 = ["hello", "welcome to idle ball", "potato"];
var lol = 1;
//set opacity to 1
function opacitySet1(speed) {
document.getElementById("talk").style.opacity = opacity;
opacity += speed;
}
//set opacity to 0
function opacitySet0(speed) {
document.getElementById("talk").style.opacity = opacity;
opacity -= speed;
}
function IntervalManager(flag, animate, time, para1) {
if (flag) {
var intervalSet = setTimeout(animate, time, para1)
}
}
function IntervalManagerII(flag, animate, time, para1) {
if (flag) {
var intervalSetII = setTimeout(animate, time, para1)
}
}
//to delay time
function nothing() {}
function message(startPart) {
document.getElementById("talk").innerHTML = messageNumber;
if (opacity >= 0 && lol == 0) {
setTimeout(nothing, 1);
IntervalManagerII(true, opacitySet0, 300, 0.005);
IntervalManager(false)
}
if (opacity <= 1 && lol == 1) {
IntervalManager(true, opacitySet1, 300, 0.005);
IntervalManagerII(false)
}
if (opacity <= 0) {
lol = 1;
IntervalManagerII(false);
messageNumber += 1;
} //this is the part that is not working
if (opacity >= 1) {
lol = 0;
IntervalManager(false);
}
};
setInterval(function() {
message(0)
});
New answer
After discussing in the comments, it turns out you think JavaScript timers are blocking the execution of the main thread. It does not work this way. Consider the following example (2 is printed almost instantly, and 1 is printed after one second).
> | setTimeout(function(){console.log(1)}, 1000);
| setTimeout(function(){console.log(2)}, 0);
< | ...
| 2
| 1
Also read this article from jQuery's creator.
Since your code is based on a wrong assumption, I think it makes no sense to work on your question any longer.
Old answer
Your setInterval timer is running a lot faster than your setTimeout timers, meaning that it queues a lot of setTimeout timers before starting to increment the opacity. During this time, the message is incremented and printed at interval max speed. After a couple of ms, all setTimeout timers start firing one after the other with almost no delay between them, and interleaving with setInterval timers, which leads to an (almost) unpredictable mess.
I a trying to create a page where the background cycles through every hex value (from #000000 to #FFFFFF). This is the JS function I am using:
function Colours(count)
{
count +=1;
if (count > 16777215)
{
count = 0;
}
hex = count.toString(16);
while (hex.length < 6)
{
hex = "0" + hex;
}
hex = "#" + hex;
document.body.style.background = hex;
window.setTimeout(Colours(count),10);
}
It is called when a button is clicked and is given the argument -1 (so the first hex value is #000000).
After some diagnosis, it seems that it only changes the colour once the recursion ends (in this case I am presuming once it reaches its' stack limit at #006446). This function will process briefly before changing the background colour to the final hex code it reached. How can I get it to change the colour every time it enters the function rather than completing the stack at the end.
You are passing the result of calling the Colours function to setTimeout. You should pass a reference to the function, and pass the arguments with the 3rd argument of setTimeout.
window.setTimeout(Colours, 10, count + 1);
function Colours(count) {
if (count > 16777215) {
count = 0;
}
hex = count.toString(16);
while (hex.length < 6) {
hex = "0" + hex;
}
hex = "#" + hex;
document.body.style.background = hex;
window.setTimeout(Colours, 10, count + 1);
}
Colours(0)
This doesn't do what you think it does:
window.setTimeout(Colours(count),10)
This is executing Colours(count) immediately and setting the timeout for the return value of that function. Since there's no timeout between executions of the function, the whole thing is blocking and the DOM won't be updated until that blocking code completes.
You want to pass a function itself, not an execution of a function. In this case it might be something like:
window.setTimeout(function () { Colours(count); }, 10)
This wraps the call in a function that isn't immediately being executed. That function will then be executed in the timeout.
Javascript can be temperamental at times. Your issue is mainly based on the fact that your code does not have the correct delay, and so the browser optimises by only showing the last iteration. The code below will fix this issue, using setTimeout. See the JSFiddle link below.
function Colours(count) {
if (count > 16777215) {
count = 0;
}
hex = count.toString(16);
while (hex.length < 6) {
hex = "0" + hex;
}
hex = "#" + hex;
document.body.style.background = hex;
window.setTimeout(Colours, 10, count + 1);
}
Colours(0)
https://jsfiddle.net/y68sfptp/1/
Edit: Sorry, just saw the previous answers.
I'm currently enhancing a website with a few animations.
I tried this code:
// Opacity is 0 in the beginning. Set
// in CSS.
// 1. Parameter: Boolean - true if making the
// element visible; false if making it vanish.
// 2. Parameter: Object
var changeOpacity = function(direction, element) {
var css = element.style;
var goStep = function(signedStep) {
css['opacity'] += signedStep;
changeOpacity(direction, element);
};
if (direction) {
if (css['opacity'] < 1.0) {
setTimeout(function() {
goStep(0.1);
}, timeStep);
}
} else {
if (css['opacity'] >= 0.1) {
setTimeout(function() {
goStep(-0.1);
}, timeStep);
} else {
css['display'] = 'none';
}
}
};
It haven't worked.
I wrote a few console.logs in the code: 'opacity' always stayed at 0.1 after the assignment.
What I expected was: 0.0 - 0.1 - 0.2 - 0.3 ...
Now I use this code:
// ...
var goStep = function(signedStep) {
css['opacity'] = +css['opacity'] + signedStep;
changeOpacity(direction, element);
};
// ...
Works fine.
But I still wonder why using the combined assignment addition operator failed.
Has anyone an idea?
You are adding string with Number, so in first case you are actually concatenating the values
See here: https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Addition_assignment
The second aproach works because you are converting css['opacity'] to a number: +css['opacity']
Try this:
var test = "0.1",
test2 = "0.1";
signedStep = 0.1;
test += signedStep;
alert(test+" is a "+typeof test);
test2 = +test2 + signedStep;
alert(test2+" is a "+typeof test2);
css['opacity'] is a string. If you add a number to a string, it will convert the number into a string and concat the two final strings.
css['opactity'] = 0.1
css['opacity'] += 0.5 // => "0.10.5"
lu.style.opacity = lu.style.opacity += 0.01;
This is part of my non-jquery fade in function for a page where i want to have a fadeIn feature but not jquery.
I'm putting an alert on the function to see what the opacity is, and every time it is 0.01, so why is it only being added on one time?
The function I use
function fadein(lu,time){
if (lu.style.opacity<1)
{
lu.style.opacity = parseFloat(lu.style.opacity, 10) + 0.01; //add 0.01 to the opacity
setTimeout(function(){fadein(lu,time)},time/100) //sets a timeout to the fadeIn function every time/100 miliseconds
}
}
Opacity is a string. You are doing string concatentation when you add to it.
console.log(typeof lu.style.opacity);
// "string"
Make sure that you are adding numbers:
lu.style.opacity = parseFloat(lu.style.opacity) + 0.01;
In case parseFloat returns NaN, this may be helpful:
lu.style.opacity = (parseFloat(lu.style.opacity) || 0) + 0.01;
Now the reason why you were not seeing a value change is this:
lu.style.opacity;
// originally empty string: ''
lu.style.opacity += 0.01
// translates to: lu.style.opacity = '' + 0.01
// which equals '0.01' which is valid, but when you do it again:
lu.style.opacity += 0.01
// it is doing this: lu.style.opacity = '0.01' + 0.01
// which is: '0.010.01'
// which is an invalid value for that css style so it retains the previous value of '0.01'
Opacity is a string.
The syntax is wrong (that +=).
lu.style.opacity = parseFloat(lu.style.opacity) + 0.01;
I think you meant either
lu.style.opacity += 0.01;
or
lu.style.opacity = lu.style.opacity + 0.01;
Throw it in a while loop to monitor your progression towards your target opacity:
var TARGET_OPACITY = 60.0;
while(lu.style.opacity < TARGET_OPACITY) {
lu.style.opacity = parseFloat(lu.style.opacity, 10) + 0.01;
}
I think you are not adding up correctly
lu.style.opacity = parseFloat(lu.style.opacity) + 0.01;
as #Pointy commented, try putting alert before u add up and after you add up.
$("#team").css("background-color","blue");
I'd like to turn the background colour of id:team to blue however I would only like to turn it this colour for 4 seconds.
How do I do this?
I've Googled around but I couldn't find anything regarding changing css for a given time frame.
Also, a fading out/in from/to the previous settings would be a nice touch.
If you want it to only appear blue for 4 seconds you could do:
var element = $( "#team" );
var oldColor = element.css( "background-color" );
element.animate( { "background-color": "blue" } )
.delay( 4000 )
.animate( { "background-color": oldColor } );
You need jQuery UI to .animate(), otherwise you can just use .css().
You have to use the timer feature:
setTimeout(function() {
$('#team').css('background-color', 'whatever');
}, 4000);
The second argument is a count in milliseconds of how long you'd like to wait before the first argument (a function) is called.
There's no built-in ability to say "go back to what it was before"; you'll have to remember the old value in your own code.
If you do not want to use the jQuery UI plugin (perhaps due to its size) then you could do the animating manually.
See the following code working in a jsFiddle.
function animblue(selector, from, to, step) {
var
target = $('#target'),
color = from,
next;
next = function () {
var hex = (Math.floor(color) < 16 ? '0' : '') + Math.floor(color).toString(16);
target.css('background-color', '#' + hex + hex + 'ff');
color += step;
if (!((color < from && color < to) || (color > from && color > to))) {
setTimeout(next, 10);
}
};
next();
}
$('#action').on('click', function () {
animblue('#target', 255, 0, -255 / 16);
window.setTimeout(function () {
animblue('#target', 0, 255, 255 / 16);
}, 4000);
});