basic setup

This commit is contained in:
nicwands
2026-05-18 15:13:23 -04:00
parent c4113658f7
commit a54e63323f
33 changed files with 2563 additions and 43 deletions

View File

@@ -0,0 +1,89 @@
import gsap from 'gsap'
import { ref, onMounted, onBeforeUnmount } from 'vue'
import { useWindowSize, useEventListener } from '@vueuse/core'
/**
* Shared global raw mouse state (only set up once)
*/
const rawMouse = {
x: ref(0),
y: ref(0),
initialized: false,
cleanup: null,
}
const useGlobalMouseListener = () => {
if (!rawMouse.initialized && !import.meta.env.SSR) {
rawMouse.initialized = true
rawMouse.cleanup = useEventListener(window, 'mousemove', (e) => {
rawMouse.x.value = e.clientX
rawMouse.y.value = e.clientY
})
}
}
/**
* Composable for smoothed mouse position with customizable smoothing and normalization.
*/
export default (options) => {
const smoothFactor = options?.smoothFactor ?? 0.1
const normalize = options?.normalize ?? false
const callback = options?.onUpdate
const { width: wWidth, height: wHeight } = useWindowSize()
const sx = ref(0)
const sy = ref(0)
useGlobalMouseListener()
const getTargetX = () =>
normalize ? rawMouse.x.value / wWidth.value : rawMouse.x.value
const getTargetY = () =>
normalize ? rawMouse.y.value / wHeight.value : rawMouse.y.value
let tween
onMounted(() => {
if (tween) tween.kill
// Start smoothing tween
tween = gsap.to(
{ x: sx.value, y: sy.value },
{
duration: 1,
ease: 'linear',
repeat: -1,
onUpdate: () => {
const newX = gsap.utils.interpolate(
sx.value,
getTargetX(),
smoothFactor,
)
const newY = gsap.utils.interpolate(
sy.value,
getTargetY(),
smoothFactor,
)
sx.value = newX
sy.value = newY
callback?.({ sx: sx.value, sy: sy.value })
},
},
)
})
onBeforeUnmount(() => {
tween?.kill()
rawMouse.cleanup()
rawMouse.initialized = false
})
return {
sx,
sy,
rawX: rawMouse.x,
rawY: rawMouse.y,
}
}