diff --git a/README.md b/README.md index 2399ffc..9388855 100644 --- a/README.md +++ b/README.md @@ -163,3 +163,19 @@ function App() { ``` + +## Scroll-Linked Animations + +`useScroll` provides reactive values based on Motion One's original [`scroll`](https://motion.dev/docs/scroll) function. + +```ts +import { useScroll } from "solid-motionone" + +// ... + +const { time, scrollX, scrollY } = useScroll() + +createEffect(() => console.log(scrollY.progress)) +``` + +These values can be used in coordination with Motion animation properties to create scroll-linked/parallax animations. diff --git a/src/index.tsx b/src/index.tsx index 8485c64..4c3206a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,4 +1,4 @@ export * from "./types.js" export {Motion} from "./motion.jsx" export {Presence, PresenceContext} from "./presence.jsx" -export {createMotion, motion} from "./primitives.js" +export {createMotion, motion, useScroll} from "./primitives.js" diff --git a/src/primitives.ts b/src/primitives.ts index 84e7a33..ac74bf7 100644 --- a/src/primitives.ts +++ b/src/primitives.ts @@ -1,8 +1,17 @@ -import {createMotionState, createStyles, MotionState, style} from "@motionone/dom" -import {Accessor, createEffect, onCleanup, useContext} from "solid-js" +import { + AxisScrollInfo, + createMotionState, + createStyles, + MotionState, + style, + scroll, + ScrollOptions, +} from "@motionone/dom" +import {Accessor, batch, createEffect, createSignal, onCleanup, onMount, useContext} from "solid-js" import {PresenceContext, PresenceContextState} from "./presence.jsx" import {Options} from "./types.js" +import {createStore, produce} from "solid-js/store" /** @internal */ export function createAndBindMotionState( @@ -65,6 +74,44 @@ export function createMotion( return state } +export function useScroll(options?: ScrollOptions): { + time: Accessor + scrollX: AxisScrollInfo + scrollY: AxisScrollInfo +} { + const [time, setTime] = createSignal(0) + const [scrollX, setScrollX] = createStore({ + current: 0, + offset: [], + progress: 0, + scrollLength: 0, + velocity: 0, + targetOffset: 0, + targetLength: 0, + containerLength: 0, + }) + const [scrollY, setScrollY] = createStore({ + current: 0, + offset: [], + progress: 0, + scrollLength: 0, + velocity: 0, + targetOffset: 0, + targetLength: 0, + containerLength: 0, + }) + + onMount(() => + scroll(({time, x, y}) => { + setTime(time) + setScrollX(x) + setScrollY(y) + }, options), + ) + + return {time, scrollX, scrollY} +} + /** * motion is a Solid directive that makes binding to elements easier. *