kanudo
kanudo

Reputation: 2219

Pure JavaScript fade in function

Hi friends i want to fade in a div when i click on another div and for that i am using following code. Code1 works fine but i require to use the Code2.

I know there is jQuery but i require to do this in JavaScript

Can you guide me that what kind of mistake i am doing or what i need change...

Code1 --- Works Fine

function starter() { fin(); }

function fin()
{
    for (i = 0; i <= 1; i += 0.01)
    {
        i=Math.round(i*100)/100;
        setTimeout("seto(" + i + ")", i * 1000);
    }
}

function seto(opa)
{
    var ele = document.getElementById("div1");
    ele.style.opacity = opa;
}

Code2 --- Does not work

function starter()
{
    var ele = document.getElementById("div1");
    fin(ele);
}
function fin(ele)
{
    for (i = 0; i <= 1; i += 0.01)
    {
        i=Math.round(i*100)/100;
        setTimeout("seto(" + ele + "," + i + ")", i * 1000);
    }
}

function seto(ele,opa)
{
    ele.style.opacity = opa;
}

Upvotes: 16

Views: 52737

Answers (8)

Kai
Kai

Reputation: 1240

Update: It seems that people enjoy my minimalistic and elegant approach, Updated for 2022:

No need for complex mechanisms. Just use CSS, which has it out of the box and has better performance overall.

Basically you achieve it with CSS by setting a transition for the opacity. In JavaScript that would be:

const div = document.querySelector('#my-div');
div.style.transition='opacity 1s';

and as a trigger you just set opacity to 0:

div.style.opacity=0;

This will create a 1 second fade out effect and you can use the trigger anywhere. The inverse can also be done to achieve a fade in effect.

Here's a working example:

const div = document.querySelector('#my-div');
div.style.transition='opacity 1s';

// set opacity to 0 -> fade out
setInterval(() => div.style.opacity=0, 1000);

// set opacity to 1 -> fade in
setInterval(() => div.style.opacity=1, 2000);
#my-div { background-color:#FF0000; width:100%; height:100%; padding: 10px; color: #FFF; }
<div id="my-div">Hello!</div>

Upvotes: 18

Justin Waulters
Justin Waulters

Reputation: 303

I just improved on laaposto's answer to include a callback. I also added a fade_out function. It could be made more efficient, but it works great for what i'm doing.

Look at laaposto's answer for implementation instructions. You can replace the JS in his fiddle with mine and see the example.

Thanks laaposto! This really helped out for my project that requires zero dependencies.

let el = document.getElementById( "div1" );

function fade_in( element, duration, callback = '' ) {
    element.style.opacity = 0;
    let last = +new Date();
    let tick = function() {
        element.style.opacity = +element.style.opacity + ( new Date() - last ) / duration;
        last = +new Date();
        if ( +element.style.opacity < 1 )
            ( window.requestAnimationFrame && requestAnimationFrame( tick ) ) || setTimeout( tick, 16 );
        else if ( callback !== '' )
            callback();
    };
    tick();
}

function fade_out( element, duration, callback = '' ) {
    element.style.opacity = 1;
    let last = +new Date();
    let tick = function() {
        element.style.opacity = +element.style.opacity - ( new Date() - last ) / duration;
        last = +new Date();
        if ( +element.style.opacity > 0 )
            ( window.requestAnimationFrame && requestAnimationFrame( tick ) ) || setTimeout( tick, 16 );
        else if ( callback !== '' )
            callback();
    };
    tick();
}

fade_out( el, 3000, function(){ fade_in( el, 3000 ) } );

Cheers!

Upvotes: 0

Yoel Duran
Yoel Duran

Reputation: 429

function hide(fn){
        var hideEle = document.getElementById('myElement');
        hideEle.style.opacity = 1;
        var fadeEffect = setInterval(function() {
        if (hideEle.style.opacity < 0.1)
        {
        hideEle.style.display='none';
        fn();
        clearInterval(fadeEffect);
        }
        else
        {
        hideEle.style.opacity -= 0.1;
        }
        }, 20);
}
function show(){
        var showEle = document.getElementById('myElement');
        showEle.style.opacity = 0;
        showEle.style.display='block';
            var i = 0;
            fadeIn(showEle,i);
            function fadeIn(showEle,i) {
                i = i + 0.05;
                seto(showEle,i);
                if (i<1){setTimeout(function(){fadeIn(showEle,i);}, 25);}
            }
            function seto(el,i)
            {
                el.style.opacity = i;
            }
}

hide(show);

Upvotes: 0

laaposto
laaposto

Reputation: 12213

Based on this site

EDIT-1
Added the functionality so that user can specify the animation duration(@Marzian comment)

You can try this:

function fadeIn(el, time) {
  el.style.opacity = 0;

  var last = +new Date();
  var tick = function() {
    el.style.opacity = +el.style.opacity + (new Date() - last) / time;
    last = +new Date();

    if (+el.style.opacity < 1) {
      (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
    }
  };

  tick();
}

var el = document.getElementById("div1");
fadeIn(el, 3000); //first argument is the element and second the animation duration in ms

DEMO

Upvotes: 29

ShAkKiR
ShAkKiR

Reputation: 929

My version

 function fadeIn($element){
  $element.style.display="block";
  $element.style.opacity=0;
  recurseWithDelayUp($element,0,1);
}
function fadeOut($element){
  $element.style.display="block";
  $element.style.opacity=1;
  recurseWithDelayDown($element,1,0);
}

function recurseWithDelayDown($element,startFrom,stopAt){
    window.setTimeout(function(){
      if(startFrom > stopAt ){
          startFrom=startFrom - 0.1;
            recurseWithDelayDown($element,startFrom,stopAt)
            $element.style.opacity=startFrom;
      }else{
        $element.style.display="none"
      } 
  },30);
}
function recurseWithDelayUp($element,startFrom,stopAt){
    window.setTimeout(function(){
      if(startFrom < stopAt ){
          startFrom=startFrom + 0.1;
            recurseWithDelayUp($element,startFrom,stopAt)
            $element.style.opacity=startFrom;
      }else{
        $element.style.display="block"
      } 
  },30);
}

Upvotes: 1

kanudo
kanudo

Reputation: 2219

Below are the complete answers to my question

ANS1 --- DEMO

function fin() {
    var i = 0;
    var el = document.getElementById("div1");
    fadeIn(el,i);
}

function fadeIn(el,i) {
    i = i + 0.01;
    seto(el,i);
    if (i<1){setTimeout(function(){fadeIn(el,i);}, 10);}
}

function seto(el,i) {
    el.style.opacity = i;
}

ANS2 --- DEMO

function fin(){
    var i = 0;
    var el = document.getElementById("div1");
    fadeIn(el,i);
}

function fadeIn(el,i) {
    var go = function(i) {
        setTimeout( function(){ seto(el,i); } , i * 1000);
    };
    for ( i = 0 ; i<=1 ; i = i + 0.01) go(i);
}

function seto(el,i)
{
    el.style.opacity = i;
}

Upvotes: 1

sejordan
sejordan

Reputation: 321

The problem here is you are using the pass-a-string method of using setTimeout. Which is basically just a hidden eval.

It's worth noting that this is a bad practice, slow performer, and security risk.

(see questions such as this: setTimeout() with string or (anonymous) function reference? speedwise)

The reason this is causing your problem is because "seto(" + ele + "," + i + ")" is going to evaluate to "seto('[object HTMLDivElement]', 1)". You really want to pass reference to the ele object -- but the value's being cast to a string when you tried concatenating an object onto a string. You can get around this by using the pass-a-function method of using setTImeout.

setTimeout(function() { seto(ele, i); }, i * 1000);

I believe making this change will make your Code2 behavior equivalent to Code1.

Upvotes: 1

Jonas m
Jonas m

Reputation: 2734

Seems like your attempting to convert your element, to a string. Try this instead

function starter()
{
    var ele = document.getElementById("div1");
    fin(ele);
}
function fin(ele)
{
    for (i = 0; i <= 1; i += 0.01)
    {
        i=Math.round(i*100)/100;
        setTimeout(function() { setto(ele,i); }, i * 1000);
    }
}

function seto(ele,opa)
{
    ele.style.opacity = opa;
}

What happens here is, that i call a anonnymous function when the timer hits, and from that function, execute my functioncall to setto.

Hope it helps. Jonas

Upvotes: 1

Related Questions