Amini
Amini

Reputation: 1792

Fade In and Fade Out using pure Javascript in a simple way

I've been trying to create a fadeIn & fadeOut animation using VanillaJS in my project but I literally don't understand what's the problem. I'm using SCSS. I made it simple for you.

I tried visibility but it didn't work too. like it appears e.g. for 200ms but then immediately disappears. In another way of explanation, it appears whenever I click on it (stable) and then goes away after 200ms (unstable).

const fade = () => {
  const box = document.querySelector('#box');
  
  box.classList.toggle('fade');
};

document.querySelector('#fadebtn').addEventListener('click', fade);
#box {
  width: 70px;
  height: 50px;
  background: #FD7A6B;
  display: none;
  opacity: 0;
  -webkit-transition: 200ms ease-in-out;
  -moz-transition: 200ms ease-in-out;
  -o-transition: 200ms ease-in-out;
  transition: 200ms ease-in-out;
}

#box.fade {
  display: block !important;
  opacity: 1 !important;
}

// I also tried this, wondered it may work, but didn't.

// .fade {
  // display: block !important;
  // opacity: 1 !important;
// }
<button type="button" id="fadebtn">Fade</button>
<div id="box"></div>

Upvotes: 1

Views: 4201

Answers (1)

Matt Kenefick
Matt Kenefick

Reputation: 1206

I wrote this due to the title of the question: "Fade in ... pure javascript ... simple way."

tl;dr https://jsfiddle.net/nqfud4j0/

The following solution is a basic example of how you can use only Javascript to fade in/out to a desired value. You could also use this with other values/properties, but it also serves as an example for basic tweening.

It's intentionally using setInterval rather than requestAnimationFrame to demonstrate the example's use of time + controlled framerate rather than a delta or 'fast as possible.' A good solution would abstract this logic into a tweening library that combines both RAF + intervals to manage latency between frames.

function fadeTo(element, toValue = 0, duration = 200) {
    // Store our element's current opacity (or default to 1 if null)
    const fromValue = parseFloat(element.style.opacity) || 1;

    // Mark the start time (in ms). We use this to calculate a ratio
    // over time that applied to our supplied duration argument
    const startTime = Date.now();

    // Determines time (ms) between each frame. Sometimes you may not
    // want a full 60 fps for performance reasons or aesthetic 
    const framerate = 1000 / 60; // 60fps
    
    // Store reference to interval (number) so we can clear it later
    let interval = setInterval(() => {
        const currentTime = Date.now();

        // This creates a normalized number between now vs when we
        // started and how far into our desired duration it goes
        const timeDiff = (currentTime - startTime) / duration;

        // Interpolate our values using the ratio from above
        const value = fromValue - (fromValue - toValue) * timeDiff;
        
        // If our ratio is >= 1, then we're done.. so stop processing
        if (timeDiff >= 1) {
            clearInterval(interval);
            interval = 0;
        }
        
        // Apply visual. Style attributes are strings.
        element.style.opacity = value.toString();
    }, framerate)
}


// Element reference
const element = document.querySelector('div');

// Fade in and out on click
element.addEventListener('click', e => {
    // Animates our element from current opacity (1.0) to 0.25 for 1000ms
    fadeTo(element, 0.25, 1000);
    
    // Waits 1s, then animates our element's opacity to 1.0 for 500ms
    setTimeout(() => {
        fadeTo(element, 1.0, 500);
    }, 1000);
});

Upvotes: 3

Related Questions