Jump to content
Search Community

Animating elements to move in opposite direction

AmanVerma test
Moderator Tag

Go to solution Solved by mvaneijgen,

Recommended Posts

Greetings to fellow devs here! I am trying to animate two children divs to move in the opposite directions using scrolltrigger. Got this suggestion from Google Bard, to put the elements in an array and then try to animate them. But the issue is, even though I am specifying opposite percentages, the elements are still moving in the same direction.  Below are CSS and React codes attached. I am using refs and the latest useGSAP hook. And here is the codepen with issue reproduced :  

here is css
 

@import url("https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Inter:wght@100..900&family=Oswald:wght@200..700&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
 
.main {
  height: 100vh;
  margin: 0;
  padding: 0;
}
.c1 {
  display: flex;
  align-items: flex-end;
  height: 100%;
  background: red;
  overflow: hidden;
}
.c1 h1 {
  text-transform: uppercase;
  color: #fff;
  font-size: 40vw;
  font-family: "Oswald";
  white-space: nowrap;
  font-weight: 500;
  letter-spacing: -30px;
}
 
.content2 {
  height: 100%;
  background: #000;
  z-index: -1;
  font-family: "Inter";
  display: grid;
  place-items: center;
  position: relative;
}
 
.data1,
.data2 {
  width: 50%;
  background: rgba(167, 255, 56, 1);
  padding: 2.5rem;
  margin: 10px auto;
  border-radius: 25px;
  z-index: 1;
}
.data2 {
  background: rgba(253, 151, 255, 1);
  position: absolute;
  z-index: 0;
}
 
@media (max-width: 750px) {
  .data1 h1 {
    font-size: 2.5rem;
    font-weight: 900;
  }
}

here is the react code:

import React, { useRef } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import "./LenScroll.css";
 
export default function LenisScroll() {
  const heading = useRef();
  const container = useRef();
 
  const data1 = useRef();
  const data2 = useRef();
 
  useGSAP(
    () => {
      gsap.registerPlugin(ScrollTrigger);
 
      const tl = gsap.timeline();
 
      tl.to(heading.current, {
        x: "-100%",
        fontWeight: 200,
        letterSpacing: "1rem",
        scrollTrigger: {
          trigger: ".c1",
          scroller: "body",
          scrub: 0.2,
          pin: true,
        },
      });
      // THIS RIGHT HERE!
      gsap.to([data1.current, data2.current], {
        y: ["-100%", "-100%"],
 
        scrollTrigger: {
          trigger: ".content2",
          scroller: "body",
          pin: true,
          scrub: 0.8,
          markers: true,
        },
      });
    },
    { scope: container.current },
  );
 
  return (
    <div ref={container} className="main">
      <div className="c1">
        <h1 ref={heading}>Aman Verma</h1>
      </div>
      <div className="content2">
        <div ref={data1} className="data1">
          <h1>Para is the easiest way to earn money as a Software engineer</h1>
        </div>
        <div ref={data2} className="data2">
          <h1>Para is the easiest way to earn money as a Software engineer</h1>
        </div>
      </div>
    </div>
  );
}

Screenshot 2024-02-07 215521.png

Screenshot 2024-02-07 215544.png

See the Pen xxBJyyY by amanopia (@amanopia) on CodePen

Link to comment
Share on other sites

  • Solution

Hi @AmanVerma welcome to the forum!

 

You can indeed use an array, but then you still need to tell it which item you want to use from the array. I've converted your x property to xPercent, seen that you want to use % values, and created a function from it from which we receive the current index of the element you want to animate. Then somewhere else we create an array with the values we want to use and then add that value when tweening your elements. Hope it helps and happy tweening! 

 

See the Pen dyrjQGr?editors=1010 by mvaneijgen (@mvaneijgen) on CodePen

  • Like 2
Link to comment
Share on other sites

Thanks for the answer! It works! I didn't know, one could use a callback. That makes me wonder, suppose I wanted to animate, just the second element in the array. 

Consider the .child2 to have an opacity of 0 initially, and we want to animate it to 1. One approach I can see is that we create an opacity array for that purpose, but wouldn't creating an opacity array for every element, make this function run redundantly for the other targets, that don't even need an opacity. Because I read somewhere in the docs that animation runs for every element in the target array. Is there a better solution to target just one element. Also, where can I read more about callbacks in gsap? Thanks!
Here is my solution: 
 

let array = [-100, 100];
let opacityArr = [1, 1]
gsap.to( [".child1",".child2" ], {
  yPercent: (index) => array[index],
  opacity: (index) => opacityArr[index],
  scrollTrigger: {
    markers: true,
    start: "top 1%",
    end: "bottom 1%",
    trigger: ".test",
    pin: true,
    scrub: 0.8,
    ease: "power2.inOut"
  }
  
})



 

Link to comment
Share on other sites

I'm not sure what you're calling a 'callback' we have eventCallbacks in the docs, but that is more when a tween has finished or it starting onComplete, onStart https://gsap.com/docs/v3/GSAP/Tween/eventCallback()/

 

In my above pen I've used Function-based values which you can read more about here  https://gsap.com/docs/v3/GSAP/gsap.to()/#function-based-values. If you're new to GSAP check out this awesome getting started guide https://gsap.com/resources/get-started/ explains a lot in a nice overview, but the docs is also a great resource in general. 

 

Personally I almost never use single gsap tweens, but I always gravitate to using a timeline. It is great in a pinch, but with a timeline you get so much more control, see below pen where a timeline has all these animations on it and ScrollTrigger controls that timeline on scrolling, some tweens start at the same time as other twens using the position parameter and other tweens wait for their turn, this al gets explained in the getting started guide, so be sure to check it out. 

 

If you need any further assistance, please  show us what you've already tried and provide a minimal demo, so that we can dive directly in the code. Hope it helps and happy tweening! 

 

See the Pen LYaBqrm?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...