Veron
Veron

Reputation: 1

How to animate a React Three Fiber "group" object with NEW framer motion?

I am building a 3D website with different pages. I am trying to make "prior" sections disappear when advancing to "further" ones by setting their y-position to -5 when not on that page.

I'm using React Three Fiber, so I've got my page elements in group objects. The default position is -5, but I am trying to add a variant that sets y:0 when the scroll is on that page.

The issue is, I'm not sure how to make the R3F group component, a motion component. With the previous version of framer-motion, we could animate a group in R3F by importing motion from framer-motion-3d, then changing any group to motion.group. It seems with the new "Motion" we are restricted to adding motion to DOM elements only? How would I animate an R3F group object directly, (rather than say, a "div"), if it is still possible?

I tried adding motion from react/motion, and making a motion.group, but it would not accept non-DOM elements. I also tried turning my groups into divs, but HTML was not allowed within the R3F Canvas.

This is my current Experience.jsx code, which I import onto the canvas in a separate file:

The groups need motion somehow, so that I can add the variants.

// Distance along z-axis between sections (as char walks fwd/backward)
const SECTION_DISTANCE = 10;

// Variants for animating sections (hiding/unhiding)
const variants = {
  home: { y: 0 },
};

export const Experience = () => {
  // State machine for revealing/hiding sections (starting at home page)
  const [section, setSection] = useState(config.sections[0]);

  const sceneContainer = useRef();
  const scrollData = useScroll();

  // Animate sceneContainer group to move through different sections
  useFrame(() => {
    sceneContainer.current.position.z =
      -scrollData.offset * SECTION_DISTANCE * (scrollData.pages - 1);
    // This moves groups in -z dir (towards camera) to sim camera moving backward (in +z dir)

    // Get current section number (current state), and acquire title from config
    setSection(
      config.sections[Math.round(scrollData.offset * (scrollData.pages - 1))]
    );
  });
  console.log(section);

  return (
    <>
      <Environment preset="sunset" />
      <Avatar />
      {/* Group containing different website sections; must match array defined in config.js */}
      <group ref={sceneContainer} animate={section}>
        {/* HOME */}
        <group variants={variants} position-y={-5}>
          <Star
            position-x={-0.009}
            position-z={0}
            position-y={1.97}
            scale={0.3}
          />
          <Float floatIntensity={2} speed={2}>
            <MacBookPro
              position-x={-1}
              position-y={0.5}
              position-z={0}
              scale={0.3}
              rotation-y={Math.PI / 4}
            />
          </Float>
          <PalmTree
            scale={0.018}
            rotation-y={THREE.MathUtils.degToRad(140)}
            position={[4, 0, -5]}
          />
          <Float
            floatIntensity={0.4}
            rotationIntensity={0.2}
            speed={2}
            floatingRange={[-0.05, 0.05]}
          >
            <Center disableY disableZ>
              <SectionTitle
                size={0.8}
                position-x={2}
                position-y={1.6}
                position-z={-3}
                bevelEnabled
                bevelThickness={0.3}
              >
                {config.home.title}
              </SectionTitle>
            </Center>
          </Float>
          <Center disableY disableZ>
            <SectionTitle
              size={1.2}
              position-x={5}
              position-z={-3}
              bevelEnabled
              bevelThickness={0.3}
              rotation-y={Math.PI / 10}
            >
              {config.home.subtitle}
            </SectionTitle>
          </Center>
        </group>

        {/* SKILLS */}
        <group position-z={SECTION_DISTANCE}>
          <group position-x={-2}>
            <SectionTitle position-x={0.4}>SKILLS</SectionTitle>
            <BookCase position-z={-2} />
            <CouchSmall
              scale={0.4}
              position-z={0}
              position-x={-0.2}
              rotation-y={Math.PI / 3}
            />
            <Lamp
              position-z={0.6}
              position-x={-0.4}
              position-y={-0.8}
              rotation-y={-Math.PI}
            />
          </group>
        </group>

        {/* CONTACT */}
        <group position-z={SECTION_DISTANCE * 4}>
          <SectionTitle position-x={0.4}>CONTACT</SectionTitle>
        </group>
      </group>
    </>
  );
};

Upvotes: 0

Views: 25

Answers (0)

Related Questions