cover

Animando translate con el scroll

author photo

Héctorbliss

@hectorbliss


robot logo saying hello

No te quedes atrás: Actualízate

Suscríbete para recibir información sobre nuevos frameworks, updates, eventos, tips, hacks y más.

Sigo jugando con MotionOne usando el scroll para crear animaciones que el usuario pueda controlar. Animaciones como esta.

enter image description here

Aquí estoy actualizando la posición de estas tres tarjetas según la posición del scroll vertical, que estoy capturando con MotionOne. Al final también utilizo el scroll para cambiar la opacidad de un segundo texto.

Bueno, si aprender a hacer esta animación con puro HTML, CSS y un poquito de JavaScript te interesa, pues quédate porque lo voy a crear paso a paso. Comencemos. 😱

🏁 Maquetación

Vamos a agregar el HTML que necesitamos para este ejemplo, recuerda que te dejo el enlace al proyecto funcionando en vivo aquí.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>fixtergeek.com</title> <link rel="stylesheet" href="src/index.css" /> </head> <body> <article> <section class=" bg-sky-500 h-[100vh] text-white text-6xl place-items-center grid px-8 text-center " > <h2>Capturando el scroll <span class="text-black">vertical</span></h2> </section> <section class="h-[300vh] bg-gray-900 relative" id="container"> <h2 class="font-bold text-6xl text-white text-center pt-20 tracking-tight" > Explora el contenido <br /> de nuestro blog </h2> <p class="text-center text-gray-500 py-4 tracking-wider"> Sigue escroleando </p> <div id="group" class=" relative sticky top-0 h-[70vh] max-w-[800px] mx-auto mb-44 z-10 " > <img id="img3" class="shadow-xl w-[220px] h-[220px] object-cover rounded-2xl" src="<https://images.pexels.com/photos/981588/pexels-photo-981588.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1>" alt="robot" /> <img id="img2" class="shadow-xl w-[220px] h-[220px] object-cover rounded-2xl" src="<https://images.pexels.com/photos/2103864/pexels-photo-2103864.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1>" alt="robot" /> <img id="img1" class="shadow-xl w-[220px] h-[220px] object-cover rounded-2xl" src="<https://images.pexels.com/photos/6975523/pexels-photo-6975523.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1>" alt="robot" /> </div> <h3 id="second_title" class=" w-full absolute bottom-[420px] font-bold text-6xl text-white text-center tracking-tight " > Seguro aprendes <br /> algo nuevo leyendo <p class=" text-center text-gray-500 py-4 tracking-wider text-sm font-normal " > Sigue leyendo todos los días </p> </h3> </section> <section class="min-h-screen bg-sky-500 text-white text-5xl text-center py-44" > <h2>No olvides suscribirte ✅</h2> <a target="_blank" href="<https://www.fixtergeek.com/blog>" className="text-sky-900" >www.fixtergeek.com/blog</a > </section> </article> <script type="module" src="/src/scroll.ts"></script> </body> </html>

Observa que tenemos tres <section>, en el de en medio se encuentran las imágenes que vamos a animar, y al final el texto que también animaremos.

También puedes ver que importamos nuestro script /src/scroll.ts.

🧑🏻‍🔬 Vamos con el CSS

Ahora vamos a agregar tres selectores CSS que necesitamos para que nuestras imágenes se posicionen.

#img1 { position: absolute; bottom: 50%; left: 50%; margin-left: -110px; } #img2 { position: absolute; bottom: 45%; left: 35%; margin-left: -110px; rotate: -12deg; z-index: -1; } #img3 { position: absolute; bottom: 45%; right: 25%; margin-left: -110px; rotate: 12deg; z-index: -1; }

Estos estilos convierten en absolutas a las imágenes y las colocan una sobre la otra. Estos son los valores por default; animaremos estos valores con JS.

🔪 Un poquillo de JS

Es momento de agregar un grupo de funciones que nos ayudarán a detonar las animaciones capturando los valores del scroll.

import { animate, scroll, spring } from 'motion'; const section = document.querySelector('#container'); const captureScroll = () => { // imgs setScrollImg1(); setScrollImg2(); setScrollImg3(); setScrollSecondTitle(); }; const setScrollSecondTitle = () => { const node = document.querySelector('#second_title'); scroll(animate(node, { opacity: [-5, 1] }), { target: section }); }; const setScrollImg3 = () => { const node = document.querySelector('#img3'); scroll( ({ y }) => { animate(node, { transform: `translate(${y.progress * -106}%,${ y.progress * 132 }%) rotate(-${y.progress * 12}deg) scale(${y.progress * -0.2 + 1})`, }); }, { target: section } ); }; const setScrollImg2 = () => { const node = document.querySelector('#img2'); scroll( ({ y }) => { animate(node, { transform: `translate(${y.progress * 120}%,${ y.progress * 137 }%) rotate(${y.progress * 12}deg) scale(${y.progress * -0.2 + 1})`, }); }, { target: section } ); }; const setScrollImg1 = () => { const node = document.querySelector('#img1'); scroll( ({ y }) => { animate(node, { transform: `translate(0,${y.progress * 124}%) scale(${ y.progress * -0.2 + 1 })`, }); }, { target: section } ); }; captureScroll();

Si observas bien, es puro código repetido. Si tu quieres refactorizar pa que quede más limpio está bien. A mi no me importa, el objetivo de este demo es educativo. 😉

¡Dime que se te ocurren mil maneras más de modificar este ejemplo!

Si le haces un cambio o lo mejoras, no dejes de hacérmelo saber.

Abrazo. Bliss. 🤓

banner

¿Quieres mantenerte al día sobre los próximos cursos y eventos?

Suscríbete a nuestro newsletter

Jamás te enviaremos spam, nunca compartiremos tus datos y puedes cancelar tu suscripción en cualquier momento 😉

robot logo saying hello
facebook icontwitter iconlinkedin iconinstagram iconyoutube icon

© 2016 - 2023 Fixtergeek