Home > Blockchain >  Using RequestAnimationFrame to create Fade in effect
Using RequestAnimationFrame to create Fade in effect

Time:07-22

I know this can be done by using CSS transition, however this 2 seconds fade-in exercise has to be done by using requestAnimationFrame, below is my code, it shows the picture but no fade in effect, also the render process is not smooth. Could you tell me where i get wrong and how to correct it? Thanks very much.

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      height: 100vh;
    }
    
    #picture {
      background-image: url("p1.jpg");
      background-repeat: no-repeat;
      background-position: center;
      background-size: 400px 400px;
      width: 80%;
      margin: auto;
      height: 80%;
    }
  </style>
</head>

<body>
  <div id="picture"></div>

  <script>
    var start = null;
    var abc = document.getElementById("picture")
    var opacity = 0;

    function step(timestamp) {
      if (!start) start = timestamp;
      var progress = timestamp - start;
      opacity = Number(window.getComputedStyle(abc).getPropertyValue("opacity"));
      if (opacity < 1) {
        opacity = opacity   0.1;
        abc.style.opacity = opacity;
      }
      if (progress < 2000) {
        window.requestAnimationFrame(step);
      }
    }

    window.requestAnimationFrame(step);
  </script>
</body>

</html>

CodePudding user response:

Your script never sets the opacity of the abc element to 0, so the opacity you read in the step function, will always be 1.

So add this line in the initialisation part:

abc.style.opacity = 0;

This shows the animation, but as you add 0.1 in each step, the fading will be completed in 10 frames, which is quite fast.

Here is an adapted version of your code:

function animateOpacity(abc, duration) {
    let start;
    
    function step(timestamp) {
        if (!start) start = timestamp;
        const opacity = (timestamp - start) / duration;
        abc.style.opacity = opacity;
        if (opacity >= 1) return;
        window.requestAnimationFrame(step);
    }
    window.requestAnimationFrame(step);
}

const abc = document.getElementById("picture");
abc.style.opacity = 0;
window.addEventListener("load", () => animateOpacity(abc, 3000));
body {
  height: 100vh;
}

#picture {
  background-image: url("https://i.stack.imgur.com/440u9.png");
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  width: 80%;
  margin: auto;
  height: 80%;
}
<div id="picture"></div>

CodePudding user response:

You have two problems.


The first is that you haven't set opacity in the CSS, so when you call opacity = Number(window.getComputedStyle(abc).getPropertyValue("opacity")); it starts out at 1 and never gets changed.

Add opacity: 0 to the #picture { rules.


window.requestAnimationFrame will be called at variable intervals depending on how busy the browser is.

This is why you have a calculation for progress which tells you how far between "the start" and "2 seconds later" you are.

Your calculation for opacity completely ignores progress. It just increments by 0.1 every time you get a new frame.

Since frames are usually quite frequent, you get from 0 to 1 in 10 frames which is very quick.

You need to calculate opacity as a proportion of progress and not make it completely independent.

  • Related