Examples
2D Stagger effect
Click on a box to start the stagger effect.
Code
<script setup lang="ts">
const blocks = ref<HTMLDivElement[]>()
const applyFuncs = computed(() => blocks.value?.map(block => useMotion(block, {
initial: {
scale: 1,
transition: { type: 'tween', duration: 300 }
}
})) ?? [])
function calculateDelays(index: number) {
return blocks.value?.map((_, idx) => 100 * Math.abs(index - idx)) ?? []
}
function startStagger (index: number) {
calculateDelays(index).forEach((delay, idx) => applyFuncs.value[idx].apply({
scale: 0,
transition: { delay }
}))
}
</script>
<template>
<ul>
<li
v-for="_, index in Array(16)"
ref="blocks"
class="block"
@click="startStagger(index)"
>
</li>
</ul>
</template>
<style scoped>
ul {
display: flex;
gap: 0.5rem
}
.block {
width: 1rem;
height: 1rem;
background-color: var(--color-primary-500);
border-radius: 0.25rem;
}
</style>
Mouse follow/mirror effect
Move your mouse or finger within the highlighted area to mirror the mouse (or finger) location on the right side.
Code
<script setup lang="ts">
import { useEventListener, useScrollLock } from "@vueuse/core";
const mouseArea = ref<HTMLDivElement>()
const box = ref<HTMLDivElement>()
const scrollLockState = ref(true)
const { apply } = useMotion(box, {
initial: {
translateX: 0,
translateY: 0,
}
})
function doMove (clientX: number, clientY: number) {
const rect = mouseArea.value?.getBoundingClientRect()
if (!rect) { return }
const { x, y } = rect
const left = clientX - x
const top = clientY - y
apply({
translateX: left,
translateY: top
})
}
useEventListener(mouseArea, 'mousemove', (e: MouseEvent) => {
doMove(e.clientX, e.clientY)
})
useEventListener(mouseArea, 'touchmove', (e: TouchEvent) => {
doMove(e.touches[0].clientX, e.touches[0].clientY)
})
useEventListener(mouseArea, 'touchstart', () => scrollLockState.value = true)
onMounted(() => {
useEventListener(document, 'touchend', () => scrollLockState.value = false)
useEventListener(document, 'touchcancel', () => scrollLockState.value = false)
const _scrollLock = useScrollLock(document.body, false)
watch(scrollLockState, (v) => _scrollLock.value = v)
})
</script>
<template>
<div class="container">
<div class="mouse-area" ref="mouseArea" />
<div class="preview-area">
<div class="box" ref="box" />
</div>
</div>
</template>
<style scoped>
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
position: relative;
width: 100%;
height: 16rem;
}
.mouse-area {
border: solid 1px var(--color-primary-500);
border-radius: 6px;
}
.preview-area {
position: relative;
overflow: hidden;
}
.box {
position: absolute;
width: 1rem;
height: 1rem;
background-color: var(--color-primary-500);
border-radius: 6px;
}
</style>