How to provide rich feedback for mouse interactions to improve user engagement?
Browsers provide mouse and keyboard interactions, but how can we maximize user feedback within the limited screen space? This has been a long-standing question for me. Here, I’ll set aside discussions about the keyboard and focus on the mouse. I aim to expand the range of mouse interactions, reducing the monotony of simple dragging or scrolling for users.
In my previous work, I created CSS animations and shader effects for event pages celebrating new phone launches. Most of the time, these were driven by the product manager’s ideas, resembling movie promotional posters that forced users into passive scrolling and swiping. This was an extremely frustrating experience.
Here, I want to take a different approach. Instead of relying on CSS interpolated animations, I aim to use physics-based animations. While they may not appear as smooth as the former, they feel more intuitive. My idea is to first provide a shared shader context, use the DOM to calculate layouts, and then implement an animation queue. This approach can broaden the possibilities, such as targeting different media types and customizable interaction events. Moreover, with tools like R3F and Drei already offering foundational support, this becomes more feasible.
<Canvas
style={{
position: "fixed",
zIndex: -1,
top: 0,
left: 0,
width: "100vw",
height: "100vh",
}}
eventSource={document.getElementById("_next")}
shadows
raycaster={{ enabled: false }}
dpr={[1, 2]}
camera={{ position: [0, 0, 10], far: 1000 }}
gl={{
powerPreference: "high-performance",
alpha: false,
antialias: false,
stencil: false,
// depth: false,
}}
onCreated={({ gl }) => gl.setClearColor(0, 0, 0, 0)}
>
<ambientLight intensity={0.4} />
{/* <PerformanceMonitor onDecline={() => degrade(true)} /> */}
{/* Renders contents "live" into a HDRI environment (scene.environment). */}
{/* <Environment
frames={degraded ? 1 : Infinity}
resolution={256}
background
blur={1}
>
<Lightformers />
</Environment> */}
</Canvas>
<animated.group
// useFramerSpring(0, { stiffness: 250, damping: 15, restDelta: 0.001, restSpeed: 0.001 })
// useFramerSpring(0, { stiffness: 150, damping: 20, restDelta: 0.01, restSpeed: 0.01 })
scale={useFramerSpring.to((s) => [s * size[0], s * size[1], 1])} }
>
<Porsche
scale={1.6}
position={[-0.5, -0.18, 0]}
rotation={[0, Math.PI / 5, 0]}
/>
</animated.group>
TODO: Separate video frames into geometry or material and handle animations individually.