Sé que esto se puede hacer usando la transición CSS, sin embargo, este ejercicio de fundido de entrada de 2 segundos se debe hacer usando requestAnimationFrame, a continuación está mi código, muestra la imagen pero no se desvanece, además el proceso de renderizado no es fluido. ¿Podría decirme dónde me equivoco y cómo corregirlo? Muchas gracias.
<!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>Su secuencia de comandos nunca establece la opacidad del elemento abc en 0, por lo que la opacidad que lee en la función de step siempre será 1.
Así que agregue esta línea en la parte de inicialización:
abc.style.opacity = 0;Esto muestra la animación, pero a medida que agrega 0.1 en cada paso, el desvanecimiento se completará en 10 cuadros, lo cual es bastante rápido.
Aquí hay una versión adaptada de su código:
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>Tienes dos problemas.
La primera es que no ha configurado la opacity en el CSS, por lo que cuando llama a opacity = Number(window.getComputedStyle(abc).getPropertyValue("opacity")); comienza en 1 y nunca cambia.
Agregue opacity: 0 a las reglas de #picture { .
window.requestAnimationFrame se llamará a intervalos variables dependiendo de qué tan ocupado esté el navegador.
Es por eso que tiene un cálculo de progress que le dice qué tan lejos está entre "el comienzo" y "2 segundos después".
Su cálculo de opacity ignora por completo progress . Simplemente aumenta en 0.1 cada vez que obtiene un nuevo marco.
Dado que los fotogramas suelen ser bastante frecuentes, obtienes de 0 a 1 de cada 10 fotogramas, lo que es muy rápido.
Debe calcular la opacity como una proporción del progress y no hacerlo completamente independiente.