14islands/r3f-scroll-rig

ScrollScene tracking CSS animation

fromwhite opened this issue · 3 comments

This issue is not a bug, it's a discussion of ideas.

Is it possible to make the scene track CSS animations?
Just like Drei's View, it can track CSS
Views use gl.scissor to cut the viewport into segments You tie a view to a tracking div which then controls the position and bounds of the viewport This allows you to have multiple views with a single, performing canvas These views will follow their tracking elements, scroll along, resize, etc

There are also more possibilities for integrating r3f and CSS animations.

ffdead commented

Hi @fromwhite - sure, it's possible but not the most performant way to animate stuff :)

You can actually try using View from Drei to solve that usecase. Here's a CodeSandbox: https://codesandbox.io/s/scrollrig-drei-view-fp4t6c?file=/src/App.jsx

The tricky part is to make sure Drei's View component doesn't interfere with the scroll-rig's global render. This seems to do the trick:

// Scroll-rig runs its global render as priority=1000 by default
// We need to render the Views after this to be visible
// (or set <GlobalCanvas globalPriority={X} />)
function DreiView({ children, index = 1001, ...props }) {
  const size = useThree((s) => s.size)
  const camera = useThree((s) => s.camera)

  // Drei's view will mess up the default camera and viewport
  // so we need to reset it manually before the next global render
  useFrame(({ gl }) => {
    gl.setScissorTest(false)
    gl.setViewport(0, 0, size.width, size.height)
    camera.aspect = size.width / size.height
    camera.updateProjectionMatrix()
  }, index + 1)

  return (
    <View index={index} {...props}>
      {children}
    </View>
  )
}

Beware of the performance impact of View because it calls getBoundingClientRect() on each frame.

I added a demo to show how you can render scissors with ScrollScene - and a note that you can also use ViewportScrollScene if you want to render custom environments in separate passes too.

ffdead commented

However, if all you do is use View you don't actually need the scroll-rig.

The main purpose of the scroll-rig is to avoid calling getBoundingClientRect() on each frame, make it easier to match exact dimensions in the DOM (scale) and also make it easier to combine the global scene with viewports.

Thank you for your reply.

Your demo is feasible.

yes indeed, this is different from Drei view component. This idea can be directly implemented using view.