useVelocity
useVelocity returns a readable store tracking the velocity of a source store’s value in units per second.
<script>
import { useSpring, useVelocity } from '@humanspeak/svelte-motion'
const x = useSpring(0)
const xVelocity = useVelocity(x)
</script>
<div>Velocity: {$xVelocity} px/s</div><script>
import { useSpring, useVelocity } from '@humanspeak/svelte-motion'
const x = useSpring(0)
const xVelocity = useVelocity(x)
</script>
<div>Velocity: {$xVelocity} px/s</div>Usage
Pass any Readable<number | string> store. The returned store emits the rate of change in units per second, settling to 0 when the source stops moving.
<script lang="ts">
import { useSpring, useVelocity, useTransform } from '@humanspeak/svelte-motion'
import { writable } from 'svelte/store'
const x = useSpring(0)
const xVelocity = useVelocity(x)
// Map velocity to visual effects
const skew = useTransform(xVelocity, [-1000, 0, 1000], [-20, 0, 20])
const opacity = useTransform(xVelocity, [-500, 0, 500], [0.5, 1, 0.5])
</script>
<div
style="transform: skewX({$skew}deg); opacity: {$opacity}"
onpointermove={(e) => x.set(e.clientX)}
>
Move your pointer
</div><script lang="ts">
import { useSpring, useVelocity, useTransform } from '@humanspeak/svelte-motion'
import { writable } from 'svelte/store'
const x = useSpring(0)
const xVelocity = useVelocity(x)
// Map velocity to visual effects
const skew = useTransform(xVelocity, [-1000, 0, 1000], [-20, 0, 20])
const opacity = useTransform(xVelocity, [-500, 0, 500], [0.5, 1, 0.5])
</script>
<div
style="transform: skewX({$skew}deg); opacity: {$opacity}"
onpointermove={(e) => x.set(e.clientX)}
>
Move your pointer
</div>With unit strings
useVelocity parses numeric values from unit strings like "120px" or "45deg":
<script>
import { useSpring, useVelocity } from '@humanspeak/svelte-motion'
const rotation = useSpring('0deg')
const rotationVelocity = useVelocity(rotation)
</script><script>
import { useSpring, useVelocity } from '@humanspeak/svelte-motion'
const rotation = useSpring('0deg')
const rotationVelocity = useVelocity(rotation)
</script>How it works
- Creates an internal
motionValuefrommotion-domfor timestamp-based velocity tracking - Subscribes to the source store and forwards each value to the motion value via
.set() - Polls
motionValue.getVelocity()viarequestAnimationFrameto emit velocity updates - Automatically stops polling when velocity settles near zero, and restarts when the source moves again
- Cleans up the RAF loop and source subscription when all subscribers unsubscribe
Performance
- On-demand polling: The RAF loop only runs while velocity is non-zero
- Auto-settle: Stops polling when movement stops, avoiding idle CPU usage
- Cleanup: Cancels animation frames and unsubscribes when no longer needed
- SSR-safe: Returns a static
readable(0)on the server
Common patterns
Momentum-based skew
<script>
import { useSpring, useVelocity, useTransform } from '@humanspeak/svelte-motion'
const x = useSpring(0)
const xVelocity = useVelocity(x)
const skew = useTransform(xVelocity, [-1000, 0, 1000], [-25, 0, 25])
</script>
<div
style="transform: skewX({$skew}deg)"
onpointermove={(e) => x.set(e.clientX)}
>
Skews with momentum
</div><script>
import { useSpring, useVelocity, useTransform } from '@humanspeak/svelte-motion'
const x = useSpring(0)
const xVelocity = useVelocity(x)
const skew = useTransform(xVelocity, [-1000, 0, 1000], [-25, 0, 25])
</script>
<div
style="transform: skewX({$skew}deg)"
onpointermove={(e) => x.set(e.clientX)}
>
Skews with momentum
</div>Velocity-driven blur
<script>
import { useSpring, useVelocity, useTransform, useMotionTemplate } from '@humanspeak/svelte-motion'
const y = useSpring(0)
const yVelocity = useVelocity(y)
const blur = useTransform(yVelocity, [-2000, 0, 2000], [10, 0, 10])
const filter = useMotionTemplate`blur(${blur}px)`
</script>
<div style="filter: {$filter}">
Blurs when moving fast
</div><script>
import { useSpring, useVelocity, useTransform, useMotionTemplate } from '@humanspeak/svelte-motion'
const y = useSpring(0)
const yVelocity = useVelocity(y)
const blur = useTransform(yVelocity, [-2000, 0, 2000], [10, 0, 10])
const filter = useMotionTemplate`blur(${blur}px)`
</script>
<div style="filter: {$filter}">
Blurs when moving fast
</div>Chaining velocities
You can derive the velocity of a velocity to get acceleration:
<script>
import { useSpring, useVelocity } from '@humanspeak/svelte-motion'
const x = useSpring(0)
const xVelocity = useVelocity(x)
const xAcceleration = useVelocity(xVelocity)
</script><script>
import { useSpring, useVelocity } from '@humanspeak/svelte-motion'
const x = useSpring(0)
const xVelocity = useVelocity(x)
const xAcceleration = useVelocity(xVelocity)
</script>API Reference
Parameters
- source
Readable<number | string>- A readable store whose value changes over time
Returns
Readable<number> - A readable store of the current velocity in units per second.
When to use
- Momentum effects: Skew, stretch, or blur elements based on how fast a value is changing
- Physics-based UI: React to acceleration or deceleration of animations
- Gesture feedback: Show speed-dependent visual feedback during pointer or scroll interactions
- Chained dynamics: Derive acceleration by passing a velocity store back into
useVelocity
See also
- useTransform - Map velocity values to visual ranges
- useMotionTemplate - Compose CSS strings from reactive stores
- useTime - Reactive time source for continuous animations
Based on Motion’s useVelocity API.