drei
drei copied to clipboard
Safari Scrolling List of Views Jittery
-
three
version: 0.162.0 -
@react-three/fiber
version: 8.15.19 -
@react-three/drei
version: 9.102.3 -
node
version: v20.11.1 -
npm
(oryarn
) version: 10.2.4
Problem description:
Scrolling a list of Views and letting go so that the inertia continues, on Safari (iPhone or macOS), results in jittering of the Views, and a slight difference in offset between the View elements and the normal UI elements.
https://github.com/pmndrs/drei/assets/6325131/cea12a4b-ad0b-44df-b719-46574797097f
Relevant code:
import React from 'react'
import { Link } from 'react-router-dom';
import { Canvas, useFrame, ThreeElements } from '@react-three/fiber'
import { View, PerspectiveCamera } from '@react-three/drei';
import { motion } from 'framer-motion';
const ScrollingList: React.FC = () => {
return (
<motion.div initial={{opacity: 0}} animate={{opacity: 1, transition: {duration: 1 }}} exit={{opacity: 0, transition: {duration: 1 }}} className="w-screen h-screen flex flex-col overflow-y-scroll overflow-x-hidden bg-white">
<h1 className="text-2xl font-black text-yellow-500 mt-12 ml-8">My Boxes</h1>
<div className="flex-grow">
{Array.apply(null, Array(20)).map(function(x, i) {
return (
<div className="h-48" key={"a"+i}>
<div className="flex flex-row pb-10 justify-center">
{Array.apply(null, Array(3)).map(function(xx, ii) {
return (
<div className="flex flex-col" key={"b"+ii}>
<div className="w-32 h-36 overflow-hidden">
<View className="w-full h-full inline-block overflow-hidden">
<PerspectiveCamera makeDefault fov={40} position={[0, 5, 20]} />
<mesh position={[0, 0, 0]} scale={[3, 3, 3]}>
<boxGeometry />
<meshStandardMaterial color="#adadad" />
</mesh>
</View>
</div>
<div className="text-center">
<Link to={"/bla/"+i+"-"+ii} className="m-auto">
<h1 className="text-xl font-black text-yellow-500">Box</h1>
<h1 className="text-sm font-black text-gray-500">500</h1>
</Link>
</div>
</div>
)
})}
</div>
</div>
)
})}
<Canvas
style={{ position: 'fixed', top: 0, bottom: 0, left: 0, right: 0, overflow: 'hidden' }}
eventSource={document.getElementById('root')!}>
<View.Port />
</Canvas>
</div>
</motion.div>
);
};
export default ScrollingList;
Suggested solution:
The effect isn't as pronounced in Chrome and Firefox, so perhaps analysis could start with the difference between them. Edit: Chrome on an iPhone has some jitter, where chrome in macOS doesn't.
Just found this as well. ScrollControls is super noticeable.
For easy replication, try this in Safari: https://codesandbox.io/p/sandbox/useintersect-and-scrollcontrols-gsm1y?file=%2Fsrc%2Findex.js
fwiw on ScrollControls I'm only seeing this jitter on iOS
Just discovered this as well. I was getting jitter in Safari and inertia in Chrome. After doing some digging and looking at a few examples I noticed something. Have a look at the following Code Sandbox:
https://codesandbox.io/s/bp6tmc
Notice the App.js uses a smooth scrolling package called @studio-freight/lenis, and it calls addEffect from @react-three/fiber to implement the Lenis instance. Also notice that the Lenis instance has { syncTouch: true } set.
The example has no jitter and no inertia, but as soon as you comment the two lines out with the Lenis instance and the addEffect, the jitter/inertia then become visible. I'm not sure why Lenis makes the jitter go away, but it's a fix for anyone looking.
I managed to fix the jitter and inertia in my own application by using ReactLenis with the useLenis hook instead of regular lenis. Hopefully this gets you further!