Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

405
Views
CSS: cómo no restablecer la animación onhover en cada hover

Tengo una animación CSS simple al pasar el mouse que hace una transición de diapositivas entre las imágenes.

Cuando el usuario pasa el cursor sobre la SECCIÓN UNO y antes de que finalice la animación, haga el desplazamiento sobre la SECCIÓN dos, la animación se reinicia y hace un movimiento retrasado.

MI CÓDIGO:

 var $circle = $('#circle'); function moveCircle(e) { TweenLite.to($circle, 0.8, { css: { left: e.pageX, top: e.pageY } }); } $(window).on('mousemove', moveCircle);
 @import "compass/css3"; @keyframes in { from { transform: translateY(-100%); } to { transform: translateY(0); } } @keyframes out { from { transform: translateY(0); } to { transform: translateY(100%); } } html { background: #0E3741; } #circle { position: absolute; pointer-events : none; width: 400px; height: 200px; top: 50%; left: 50%; margin: -50px 0 0 -50px; } #circle .circle-wrapper { overflow: hidden; width: 400px; height: 200px; position: relative; } #circle img { position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 400px; height: 200px; object-fit: cover; overflow: hidden; } #wrapper { display: flex; flex-direction: column; } .special-element { width: 100%; height: 100px; display: flex; justify-content: center; align-items: center; } #one { background: blue; } #two { background: red; } #one:hover ~ #circle .circle-wrapper #imgOne { animation: in 1s ease-in-out; z-index: 2; } #one:hover ~ #circle .circle-wrapper #imgTwo { animation: out 1s ease-in-out; } #two:hover ~ #circle .circle-wrapper #imgTwo { animation: in 1s ease-in-out; z-index: 2; } #two:hover ~ #circle .circle-wrapper #imgOne { animation: out 1s ease-in-out; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.4/TweenMax.min.js"></script> <section id="wrapper"> <section class="special-element" id="one"> section one </section> <section class="special-element" id="two"> section two </section> <div id="circle"> <div class="circle-wrapper"> <img id="imgOne" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg"> <img id="imgTwo" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg"> </div> </div> </section>

¿Hay alguna solución para evitar este problema de retraso?

¿Quizás hay alguna solución a cómo puedo resolverlo y hacer que esta animación sea fluida?

Estoy buscando algo como animación en este sitio web .

over 4 years ago · Santiago Trujillo
4 answers
Answer question

0

Creo que ese problema se debe a la "función de círculo en movimiento". Mover el elemento dom con izquierda y derecha no es bueno para el rendimiento. Debes mover el círculo con "transformar". Transforme las ejecuciones con la aceleración de GPU y funciona mejor y hace que el movimiento sea fluido.

Prueba este código.

 function moveCircle(e) { TweenLite.to($circle, 0.8, { css: { transform: `translate(${e.pageX}px, ${e.pageY}px)` } }); }
over 4 years ago · Santiago Trujillo Report

0

Versión actualizada

Puedes hacer una versión simplificada con gsap. Probablemente sea mejor no mezclar demasiado css simple con gsap, a menos que use css dentro de la biblioteca gsap. Porque gsap manipulará algunos de los accesorios. Por ejemplo, la transformación. Y es mejor usar transform que solo left/top porque está acelerado por hardware.

He hecho algunas mejoras en el código que he publicado antes. Se ve más suave ahora. Además, he agregado un pequeño efecto de zoom y desplazamiento horizontal, similar a la animación en el sitio web al que se hace referencia. Además, la animación ahora comienza desde abajo.

La animación está muy bien hecha en la página de referencia. Está hecho con WebGL. Esta no es su animación de todos los días y requiere bastante esfuerzo para que funcione, al menos para alguien que no es diseñador. Utiliza una matriz de transformación 3d y algunos otros efectos juntos.

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css" /> <script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script> <script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script> <style type="text/css"> .section { display: block; width: 100%; height: 300px; border-bottom: 1px solid red; } .overlay { position: absolute; top: 0; left: 0; display: none; background: transparent; z-index: -1; } .stack { position: relative; min-width: 300px; min-height: 300px; width: 480px; height: 320px; max-width: 480px; max-height: 320px; overflow: hidden; z-index: 1; } .img { position: absolute; top: 0; left: 0; width: auto; height: auto; max-width: 100%; object-fit: contain; z-index: -1; } </style> </head> <body> <main class="main"> <section class="section section-1" data-img="img-1">section 1</section> <section class="section section-2" data-img="img-2">section 2</section> <div class="overlay"> <div class="stack"> <img id="img-1" class="img" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg"> <img id="img-2" class="img" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg"> </div> </div> </main> <script type="application/javascript"> window.onload = () => { const overlay = document.querySelector(".overlay"); const stack = document.querySelector(".stack"); const s1 = document.querySelector(".section-1"); const s2 = document.querySelector(".section-2"); const main = document.querySelector(".main"); const overlaySize = { width: 480, height: 320 }; const easeFunc = "sine.inOut"; const easeDuration = 0.5; let animation; let activeSection; let currentTarget; function createAnimation() { //console.log('create animation'); t1 = gsap.timeline({ paused: true }); t1.to(currentTarget, { zIndex: 2, display: "block" }, 0); t1.fromTo(currentTarget, { y: "100%" }, { y: 0, duration: easeDuration, ease: easeFunc }, 0); t1.to(currentTarget, { scale: 1.25, transformOrigin: "center", duration: easeDuration, ease: easeFunc }, 0); stack.querySelectorAll(".img").forEach((it) => { if (it !== currentTarget) { t1.to(it, { zIndex: -1 }, 0); t1.to(it, { scale: 1, transformOrigin: "center" }, 0); t1.to(it, { display: "none" }, easeDuration); } }); return t1; } function onMouseLeave(e) { const target = e.target; //console.log("leave", e.target); if (target === activeSection) { gsap.set(overlay, { display: "none" }); currentTarget = null; } } function onMouseEnter(e) { currentTarget = stack.querySelector(`#${e.target.dataset.img}`); gsap.set(overlay, { display: "block" }); if (!animation) { //console.log("undefined animation") animation = createAnimation(); animation.play(); } else if (animation.isActive()) { //console.log("still active"); animation.timeScale(10); // fast forward the rest of the animation animation = createAnimation(); animation.timeScale(1).play(); } else { //console.log("no longer active"); animation = createAnimation(); animation.play(); } } function onMouseMove(e) { const hoveredEl = document.elementFromPoint(e.pageX, e.pageY); if (hoveredEl.classList.contains("section")) { if (activeSection !== hoveredEl) { activeSection = hoveredEl; } } else if (hoveredEl.classList.contains("overlay") || hoveredEl.classList.contains("stack") || hoveredEl.classList.contains("pointer")) { // do nothing } else { if (activeSection) { activeSection = null; } } if (currentTarget) { // update overlay gsap.set(overlay, { x: e.pageX - overlaySize.width / 2, y: e.pageY - overlaySize.height / 2 }); // add a little horizontal-shift effect const dx = window.innerWidth / 2 - e.pageX; const offsetX = dx / window.innerWidth / 2 * 100; gsap.to(currentTarget, { x: offsetX * 2, duration: 2 }, 0); } } gsap.set(overlay, { x: 0, y: 0 }); stack.querySelectorAll('.img').forEach((it) => gsap.set(it, { x: 0, y: "100%" })); window.addEventListener("mousemove", onMouseMove); s1.addEventListener("mouseleave", onMouseLeave); s2.addEventListener("mouseleave", onMouseLeave); s1.addEventListener("mouseenter", onMouseEnter); s2.addEventListener("mouseenter", onMouseEnter); } </script> </body> </html>

respuesta antigua

 I have been playing around a little bit with the gsap library today. I've honestly never done anything with or like it. Tried to do it with the x and y params that you may pass to gsap. It will take care of the transformations - also the TimeLine stuff is quite handy. The result is not that great, also the animations look like it could be done better, but maybe it might still help you out. You could also improve some of the logic and animation probably. At least it runs quite stable - performance wise. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css" /> <script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script> <script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script> <style type="text/css"> .section { display: block; width: 100%; height: 200px; border-bottom: 1px solid red; } .overlay { position: absolute; top: 0; left: 0; display: none; border: none; // 1px dashed black; background: transparent; // lavender; overflow: hidden; } .stack { position: relative; left: 0; right: 0; top: 0; bottom: 0; min-width: 300px; min-height: 300px; width: 480px; height: 320px; z-index: 0; } .anim-img { position: absolute; top: 0; left: 0; width: auto; height: auto; max-width: 100%; object-fit: contain; z-index: 1; } </style> </head> <body> <main class="main"> <section class="section section-1">section 1</section> <section class="section section-2">section 2</section> <div class="overlay"> <div class="stack"> <img id="img-1" class="anim-img" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg"> <img id="img-2" class="anim-img" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg"> </div> </div> </main> <script type="application/javascript"> window.onload = () => { const overlay = document.querySelector(".overlay"); const img1 = document.getElementById("img-1"); const img2 = document.getElementById("img-2"); const s1 = document.querySelector(".section-1"); const s2 = document.querySelector(".section-2"); const main = document.querySelector(".main"); let anim; let isS1active = false; let isS2active = false; let showEl; let hideEl; let leaveTimeout; function reverseFadeInOut(showEl, hideEl) { console.log("create reverse timeline anim -> ", { showEl, hideEl }); const tl = gsap.timeline({ paused: true }); tl .to(showEl, { zIndex: 1 }, 0) .to(hideEl, { zIndex: 10 }, 0) .to(hideEl, { y: "-100%", duration: 0.375 }, 0) .to(hideEl, { display: "none" }, 0.375) .to(hideEl, { zIndex: 1 }, 0.375) .to(showEl, { display: "block", zIndex: 10 }, 0.375) .fromTo(showEl, { y: "-100%" }, { y: 0, duration: .375 }, 0.375) .to(hideEl, { display: "none" }); return tl; } function fadeInOut(showEl, hideEl) { console.log("create timeline anim -> ", { showEl, hideEl }); const tl = gsap.timeline({ paused: true }); tl .to(hideEl, { zIndex: 1 }, 0) .to(showEl, { display: "block", zIndex: 10 }, 0) .fromTo(showEl, { y: "-100%" }, { y: 0, duration: .75 }, 0) .fromTo(hideEl, { y: 0 }, { y: "-100%", duration: .75 }, 0) .to(hideEl, { display: "none" }, 0.75); return tl; } function animateImage() { if (isS1active || isS2active) { if (isS1active) { showEl = img1; hideEl = img2; } else if (isS2active) { showEl = img2; hideEl = img1; } if (!anim) { console.log("create new animation"); anim = fadeInOut(showEl, hideEl); anim.play(); } else { console.log("anim active:", anim.isActive()); if (anim.isActive()) { console.log("reverse"); anim.kill(); anim = reverseFadeInOut(showEl, hideEl); anim.play(); } else { anim = fadeInOut(showEl, hideEl); anim.play(); } } } } function moveOverlay(e) { e.preventDefault(); e.stopPropagation(); gsap.set(overlay, { x: e.pageX + 15, y: e.pageY + 15, display: isS1active || isS2active ? "block" : "none" }); } function mouseOver(e, el, isEntering) { e.preventDefault(); e.stopPropagation(); el.classList.toggle("active"); isS1active = s1.classList.contains("active"); isS2active = s2.classList.contains("active"); if (isEntering) { clearTimeout(leaveTimeout); animateImage(); } else { leaveTimeout = setTimeout(() => { if (anim) { console.log("kill anim"); anim.kill(); anim = null; } gsap.timeline({ onComplete: () => { console.log("clear props"); gsap.set(".anim-img", { clearProps: true }); } }); }, 500); } } gsap.set(overlay, { x: "0", y: "0" }); gsap.set(img1, { x: "0", y: "-100%" }); gsap.set(img2, { x: "0", y: "-100%" }); window.addEventListener("mousemove", moveOverlay); s1.addEventListener("mouseenter", (e) => { mouseOver(e, s1, true); }); s1.addEventListener("mouseleave", (e) => { mouseOver(e, s1, false); }); s2.addEventListener("mouseenter", (e) => { mouseOver(e, s2, true); }); s2.addEventListener("mouseleave", (e) => { mouseOver(e, s2, false); }); } </script> </body> </html>

over 4 years ago · Santiago Trujillo Report

0

Sí, lo hay, modificando el valor del segundo parámetro de TweenLite.to , porque esa es la duration , vea más aquí: http://www.tud.ttu.ee/im/Jaak.Henno/FlashDevelop/greensock-as3 /greensock-as3/docs/com/greensock/TweenLite.html#to()

ingrese la descripción de la imagen aquí

 var $circle = $('#circle'); function moveCircle(e) { TweenLite.to($circle, 0.1, { css: { left: e.pageX, top: e.pageY } }); } $(window).on('mousemove', moveCircle);
 @import "compass/css3"; @keyframes in { from { transform: translateY(-100%); } to { transform: translateY(0); } } @keyframes out { from { transform: translateY(0); } to { transform: translateY(100%); } } html { background: #0E3741; } #circle { position: absolute; pointer-events : none; width: 400px; height: 200px; top: 50%; left: 50%; margin: -50px 0 0 -50px; } #circle .circle-wrapper { overflow: hidden; width: 400px; height: 200px; position: relative; } #circle img { position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 400px; height: 200px; object-fit: cover; overflow: hidden; } #wrapper { display: flex; flex-direction: column; } .special-element { width: 100%; height: 100px; display: flex; justify-content: center; align-items: center; } #one { background: blue; } #two { background: red; } #one:hover ~ #circle .circle-wrapper #imgOne { animation: in 1s ease-in-out; z-index: 2; } #one:hover ~ #circle .circle-wrapper #imgTwo { animation: out 1s ease-in-out; } #two:hover ~ #circle .circle-wrapper #imgTwo { animation: in 1s ease-in-out; z-index: 2; } #two:hover ~ #circle .circle-wrapper #imgOne { animation: out 1s ease-in-out; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.4/TweenMax.min.js"></script> <section id="wrapper"> <section class="special-element" id="one"> section one </section> <section class="special-element" id="two"> section two </section> <div id="circle"> <div class="circle-wrapper"> <img id="imgOne" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg"> <img id="imgTwo" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg"> </div> </div> </section>

over 4 years ago · Santiago Trujillo Report

0

El sitio web está usando lienzo para la presentación de diapositivas en movimiento y han usado webgl para el tipo suave de efectos de revelación.

 <div class="site-footer"> <div class="js-scroll-height"></div> <canvas width="780" height="624" class="js-webgl" style="width: 1041px;height: 833px;opacity: 1;border: 1px solid brown;"></canvas> </div>


Podemos crear un efecto de revelación similar usando animación simple y manipulación del índice z:

 var $cursor = $('#cursor'); function movecursor(e) { TweenLite.to($cursor, 0.8, { css: { left: e.pageX, top: e.pageY } }); } $(window).on('mousemove', movecursor); let topImg = null; $('.special-element').mouseenter((e) => { //make all images at same level $('.img-wrapper').css({ zIndex: '1' }); //make last focused image at second highest level if (topImg) topImg.css({ zIndex: '2' }); //make current image as topImage let atr = $(e.target).attr('data-img'); topImg = $('.img-wrapper[data-img="' + atr + '"]'); //make it topmost topImg.css({ zIndex: '3' }); });
 :root { --cursor-img-height: 30vh; --cursor-img-width: 30vw; } html, body { background: #0E3741; } #wrapper { display: flex; flex-direction: column; } .special-element { width: 100%; height: 33vh; display: flex; justify-content: center; align-items: center; font-size: 2rem; } .special-element:nth-child(1) { background: lightblue; } .special-element:nth-child(2) { background: lightcoral; } .special-element:nth-child(3) { background: lightgreen; } #cursor { position: absolute; pointer-events: none; margin: 0; margin-top: calc(var(--cursor-img-height) * -0.5); margin-left: calc(var(--cursor-img-width) * -0.5); overflow: hidden; width: var(--cursor-img-width); height: var(--cursor-img-height); } .img-wrapper { position: absolute; bottom: 0; left: 0; width: var(--cursor-img-width); height: var(--cursor-img-height); overflow: hidden; } .img-wrapper>img { position: absolute; bottom: 0; left: 0; width: var(--cursor-img-width); height: var(--cursor-img-height); object-fit: fill; z-index: 1; } .special-element[data-img="one"]:hover~#cursor [data-img="one"], .special-element[data-img="two"]:hover~#cursor [data-img="two"], .special-element[data-img="three"]:hover~#cursor [data-img="three"] { animation: slide .8s ease-in-out; } @keyframes slide { from { height: 0px; transform: scale(1.2); } to { height: (--cursor-img-height); transform: scale(1); } }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.4/TweenMax.min.js"></script> <section id="wrapper"> <section class="special-element" data-img="one">food</section> <section class="special-element" data-img="two">animal</section> <section class="special-element" data-img="three">night</section> <div id="cursor"> <div class="img-wrapper" data-img='one'> <img src="https://picsum.photos/id/674/400/200"> </div> <div class="img-wrapper" data-img='two'> <img src="https://picsum.photos/id/433/400/200"> </div> <div class="img-wrapper" data-img='three'> <img src="https://picsum.photos/id/901/400/200"> </div> </div> </section>


Ver en modo página completa.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!