ScrollControls
Scroll controls create a HTML scroll container in front of the canvas. Everything you drop into the <Scroll>
component will be affected.
You can listen and react to scroll with the useScroll
hook which gives you useful data like the current scroll offset
, delta
and functions for range finding: range
, curve
and visible
. The latter functions are especially useful if you want to react to the scroll offset, for instance if you wanted to fade things in and out if they are in or out of view.
import { ScrollControls } from '@react-three/drei'
<ScrollControls
pages={3} // Each page takes 100% of the height of the canvas
distance={1} // A factor that increases scroll bar travel (default: 1)
damping={4} // Friction, higher is faster (default: 4)
horizontal={false} // Can also scroll horizontally (default: false)
infinite={false} // Can also scroll infinitely (default: false)
>
{/* You can have components in here, they are not scrolled, but they can still
react to scroll by using useScroll! */}
<Scroll>
<Foo position={[0, 0, 0]} />
<Foo position={[0, viewport.height, 0]} />
<Foo position={[0, viewport.height * 1, 0]} />
</Scroll>
<Scroll html>
<h1>html in here (optional)</h1>
<h1 style={{ top: '100vh' }}>second page</h1>
<h1 style={{ top: '200vh' }}>third page</h1>
</Scroll>
</ScrollControls>
function Foo() {
const ref = useRef()
const data = useScroll()
useFrame(() => {
// data.offset = current scroll position, between 0 and 1, dampened
// data.delta = current delta, between 0 and 1, dampened
// Will be 0 when the scrollbar is at the starting position,
// then increase to 1 until 1 / 3 of the scroll distance is reached
const a = data.range(0, 1 / 3)
// Will start increasing when 1 / 3 of the scroll distance is reached,
// and reach 1 when it reaches 2 / 3rds.
const b = data.range(1 / 3, 1 / 3)
// Same as above but with a margin of 0.1 on both ends
const c = data.range(1 / 3, 1 / 3, 0.1)
// Will move between 0-1-0 for the selected range
const d = data.curve(1 / 3, 1 / 3)
// Same as above, but with a margin of 0.1 on both ends
const d = data.curve(1 / 3, 1 / 3, 0.1)
// Returns true if the offset is in range and false if it isn't
const e = data.visible(2 / 3, 1 / 3)
// The visible function can also receive a margin
const f = data.visible(2 / 3, 1 / 3, 0.1)
})
return <mesh ref={ref} {...props} />
loading
loading
loading
loading
loading
loading