fix: handle hardware acceleration disabled scenario in demo site (#3082)

* fix: handle hardware acceleration disabled scenario in demo site

This commit improves the demo site's error handling when hardware acceleration
is disabled in the browser. The changes include:

- Improved fallback UI with a more informative message

The fallback scene now shows:
- A static image of the Zustand ogimage

This fixes the issue where the demo site would break without any feedback
when hardware acceleration is disabled.

Testing:
- fallback works when hardware acceleration is disabled

* fixed code format

---------

Co-authored-by: Daishi Kato <dai-shi@users.noreply.github.com>
This commit is contained in:
Rahul Singh 2025-04-16 05:06:12 +05:30 committed by GitHub
parent 21fc1b1522
commit 4d3a0176ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -147,49 +147,87 @@ function Effects() {
)
}
export default function Scene() {
function FallbackScene() {
return (
<Canvas>
<div
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#010101',
}}
>
<img
src="/ogimage.jpg"
alt="Zustand Bear"
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
}}
/>
</div>
)
}
export default function Scene() {
const [error, setError] = useState(null)
if (error) {
return <FallbackScene />
}
return (
<Canvas onError={setError}>
<Experience />
<Effects />
</Canvas>
)
}
function Canvas({ children }) {
function Canvas({ children, onError }) {
extend({ Mesh, PlaneGeometry, Group })
const canvas = useRef(null)
const root = useRef(null)
useLayoutEffect(() => {
if (!root.current) {
root.current = createRoot(canvas.current).configure({
events,
orthographic: true,
gl: { antialias: false },
camera: { zoom: 5, position: [0, 0, 200], far: 300, near: 50 },
onCreated: (state) => {
state.events.connect(document.getElementById('root'))
state.setEvents({
compute: (event, state) => {
state.pointer.set(
(event.clientX / state.size.width) * 2 - 1,
-(event.clientY / state.size.height) * 2 + 1,
)
state.raycaster.setFromCamera(state.pointer, state.camera)
},
})
},
})
try {
if (!root.current) {
root.current = createRoot(canvas.current).configure({
events,
orthographic: true,
gl: { antialias: false },
camera: { zoom: 5, position: [0, 0, 200], far: 300, near: 50 },
onCreated: (state) => {
state.events.connect(document.getElementById('root'))
state.setEvents({
compute: (event, state) => {
state.pointer.set(
(event.clientX / state.size.width) * 2 - 1,
-(event.clientY / state.size.height) * 2 + 1,
)
state.raycaster.setFromCamera(state.pointer, state.camera)
},
})
},
})
}
const resize = () =>
root.current.configure({
width: window.innerWidth,
height: window.innerHeight,
})
window.addEventListener('resize', resize)
root.current.render(children)
return () => window.removeEventListener('resize', resize)
} catch (e) {
onError?.(e)
}
const resize = () =>
root.current.configure({
width: window.innerWidth,
height: window.innerHeight,
})
window.addEventListener('resize', resize)
root.current.render(children)
return () => window.removeEventListener('resize', resize)
}, [children])
}, [children, onError])
return (
<canvas