IF condition is always false in this case - javascript

I am trying to reduce opacity with JavaScript. But the problem is that 'if' condition is always false therefor the opacity is getting 0. Please can anyone explain why this is happening and the correct solution.
var opacity = 1;
var decrement = 0.01;
var id = setInterval(frame, 10);
function frame(){
if (opacity == 0.4) //It is always false..
{
clearInterval(id);//Not able to clear Interval
}
else
{
opacity = opacity-decrement;
document.getElementsByClassName('menu_bar')[0].style.backgroundColor='rgba(66,64,61,'+opacity+')';
}
}

if(Math.abs(opacity - 0.4) < 0.01) {
Floating point math is "broken", therefore you have to be fault tolerant.

Instead of using opacity == 0.4 in your code, try using opacity < 0.5 or opacity <= 0.4 as fractions are not very reliable in javascript.
Try running 1-0.1-0.1-0.1-0.1-0.1-0.1 (The math that happens before your == 0.4 check should return true) in your console to see what I mean.

As mentioned, the floating point math is broke.
A simple fix is to use integers and divide the end result with 100.
That will also avoid any extra Math.abs, or calc, at every interval.
Stack snippet
var opacity = 100;
var decrement = 1;
var id = setInterval(frame, 10);
function frame() {
if (opacity == 40)
{
clearInterval(id);
} else {
opacity = opacity - decrement;
//document.getElementsByClassName('menu_bar')[0].style.backgroundColor='rgba(66,64,61,'+opacity/100+')';
document.body.style.backgroundColor='rgba(66,64,61,'+opacity/100+')';
}
}

You can use opacity.toFixed(2) to restrict the decimal digits to 2, this will sole the issue
var opacity = 1;
var decrement = 0.01;
var id = setInterval(frame, 10);
function frame(){
if (opacity.toFixed(2) == 0.40) //It is always false..
{
console.log("Cleared");
clearInterval(id);//Not able to clear Interval
}
else
{
opacity = opacity-decrement;
// document.getElementsByClassName('menu_bar')[0].style.backgroundColor='rgba(66,64,61,'+opacity+')';
}
}

Related

How to set probability of something happens based on variable

I wonder how to set probability of something happens based on a variable.
Let's say:
var a = "5235235";
var b = "5235235";
var rand = Math.random();
if (rand < 0.3) {
console.log("30% chance");
} else {
console.log("70% chance");
}
I have tried the percentage chances like so, but I don't really know how to set for example 70% chance of something happened if variable a is equal to variable b. Any ideas?
Use a variable to hold the percentage, instead of hard-coding it, then assign it depending on the condition.
var pct = 0.3;
if (a == b) {
pct = 0.7;
}
var rand = Math.random();
if (rand < pct) {
console.log("Success!");
} else {
console.log("Failure. :(");
}
okay so if you want two mutually exclusive events with one occurring 30% of the time and the other occurring 70% of the time, then
chance = random.randint(1,100)
if chance <= 30:
print "30% chance of getting this"
elif chance <= 70:
print "70% change of getting this"

setInterval response only once instead of 1000

I want to change the opacity of table with setInterval:
window.setInterval(function () {
if (document.getElementById("goalkeepers").style.opacity != 1)
document.getElementById("goalkeepers").style.opacity = document.getElementById("goalkeepers").style.opacity + 0.001;
}, 1);
When I run this code it do it only once, the opacity of the table is only 0.001.
What is the problem?
There are several things wrong with the code itself:
DRY, you are calling getElementById to get the same element a LOT.
You are assuming that 0.001 + 0.001 + 0.001 + ... a thousand times will add up to exactly 1. This is not true in computers, because of how floating point numbers work. You should use < 1 instead of != 1
Retrieving a style is always a string. Therefore the result is trying to be 0.0010.001, ie. concatenation.
You are using an interval of 1ms. Intervals should generally not be less than about 20.
Try:
var tbl = document.getElementById('goalkeepers');
tbl.style.opacity = 0;
tbl.style.transition = "opacity 1s linear";
setTimeout(function() {
// delay the actual opacity setting so it will be transitioned
tbl.style.opacity = 1;
},10);
These guys beat me to it while I was making a fiddle, But I will post anyway.
var gk = document.getElementById("goalkeepers"),
animation = window.setInterval(function () {
if (gk.style.opacity < 1) {
gk.style.opacity = Number(gk.style.opacity) + 0.001;
}
else {
clearInterval(animation);
}
}, 1);
They both are correct about using < istead of != for the float type comparison, the string value of style.xxx and only calling document.getElementById once.
You should consider excepting one of their answers.
Try this
var t= window.setInterval(function () {
if (parseInt(document.getElementById("goalkeepers").style.opacity) != 1)
{
document.getElementById("goalkeepers").style.opacity = Number(document.getElementById("goalkeepers").style.opacity) + 0.001;
}
else
{
clearInterval(t);
}
}, 1);
You opacity is not incrementing, so used Number() also you have clear the interval once opacity reached 1 else it will keep calling might slow down your browser after some time.

JavaScript: Opacity should reduce to 0 and then become negative

I have a javaScript function.
JavaScript:
function opacZero(object){
var presentOpacity = (object.style.opacity);
object.style.opacity =presentOpacity-0.2;
setTimeout( function(){opacZero(object)}, 40);
}
Now when I pass som eobject to this function, its opacity should reduce till 0 and go beyond 0 (as I am not clearing the timeout anywhere). But this is not happening. The opacity reduces to 0.20000000000000007 and reduces no more. But when I subtract 0.3 (or more) instead of 0.2, it is giving the desired result. But why not with numbers less than 0.2. I have no idea why this is happening. Help PLease
This is due to how Javascript handles floating point numbers. Check out this SO question for some suggestions on how to work around it.
EDIT
Here's a way to work around it:
function opacZero(object){
var presentOpacity = Math.floor(object.style.opacity * 10);
object.style.opacity = (presentOpacity - 2) / 10;
setTimeout( function(){opacZero(object)}, 40);
}
This is a possible work around:
function opacZero(object){
curOpac = curOpac < 0.1 ? 0 : curOpac - 0.2;
object.style.opacity = curOpac;
setTimeout( function(){
opacZero(object)
}, 400);
console.log( curOpac );
}
var test = document.getElementById( 'test' ),
curOpac = 1;
test.style.opacity = 1;
opacZero( test );
http://jsfiddle.net/daCrosby/bhTNC/1/
Seems a little more straightforward to just check for the troublesome small values and force those to 0. Also probably a good idea to stop the timer once you hit 0:
function opacZero(object){
var newOpacity = object.style.opacity - 0.2;
if (newOpacity < 0.2) {
newOpacity = 0;
}
object.style.opacity = newOpacity;
if (newOpacity !== 0) {
setTimeout(function(){opacZero(object)}, 40);
}
}
Working demo: http://jsfiddle.net/jfriend00/8qkFN/
Or, if you want something briefer:
function opacZero(object){
object.style.opacity = object.style.opacity < 0.4 ? 0 : object.style.opacity - 0.2;
if (object.style.opacity != 0) {
setTimeout(function(){opacZero(object)}, 40);
}
}

Javascript: Increasing/decreasing number to target

What is the best way to count from one preset number to a higher or lower number on input, and show the animation of the change?
There will be an initial amount, let say 100; and when we give it an increased or decreased number, let's say 200, the original 100 will count up animated to 200.
You can use setInterval like this:
var count = 100;
var number = 110;
var interval = setInterval(function(){
document.getElementById('elementID').innerHTML = ++count;
if (count === number) { clearInterval(interval) }
}, 500);
Use ++count if you want to increase or --count if you want to decrease.
Working Example
Not 100% sure I understand what you mean, but the count thing is simple:
function count() {
var i; //declare i for use later in the function
for (i = 100; i <= 200; i++) {
alert(i);
}
}

JavaScript setTimeout() Method on Animation

I have three yellow bars and each of them needs to come from left to right. For that, I have produced this code, but it only works on the last one. Can anyone correct this code; I need to work with pure JavaScript. I am not using any framework. Thanks.
window.onload = function(){
var yellowTitles = document.getElementById('magazine-brief').getElementsByTagName('h2');
for(i=0; i< yellowTitles.length; i++) {
var header = yellowTitles[i];
var timer = i*500;
var yellowBar = setTimeout(animeYellowBar,timer);
function animeYellowBar(){
header.style.left= "0";
}
}
}
Here's how I'd solve the problem:
var yellows = document.getElementById('magazine-brief').getElementsByTagName('h2');
// this will force the header number to be bound correctly
// also animates the div across the page by tracking the current position of x
function createMotion(num){
var currPos = 0;//current x position
var delta = 10;//move by this amount
setInterval(function(){
currPos += delta
yellows[num].style.left = currPos;
}, num * 500);
}
for (var i = 1; i < yellows.length; i++)
{
createMotion(i);
}
Note the function "createMotion" - added so the number "i" is correctly reference in the setInterval function.
Shouldn't you be incrementing your CSS left value instead of just setting it to 0? Why have a timeout at all if you're just going to set the value without gradually incrementing or decrementing?
If you do actually want to use a gradual animation, look at this tutorial : http://www.schillmania.com/content/projects/javascript-animation-1/
Very descriptive and possibly what you want.
By the time your timeout function runs, header refers to your last h2.
Try editing your timeout function to this:
function animeYellowBar(){
var thisheader=header;
thisheader.style.left= "0";
}
var yellows = document.getElementById('magazine-brief').getElementsByTagName('h2');
for (var i = 0; i < yellows.length; i++)
{
(function(idx, el){
window.setTimeout(function(){
var interval = window.setInterval(function(){
el.style.left = parseInt(el.style.left) + 10; // adjust this movement step
if (parseInt(el.style.left) >= 0)
{
el.style.left = 0;
window.clearInterval(interval);
}
}, 100); // adjust this number for animation speed
}, (idx++) * 500);
})(i, yellows[i]);
}

Categories

Resources