mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 06:29:30 -07:00
1 line
4.5 KiB
JSON
1 line
4.5 KiB
JSON
{"name":"GridMotion","title":"GridMotion","description":"Perspective moving grid lines based on cusror position.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<script setup lang=\"ts\">\nimport { ref, onMounted, onBeforeUnmount, computed, useTemplateRef } from 'vue';\nimport { gsap } from 'gsap';\n\ninterface GridMotionProps {\n items?: string[];\n gradientColor?: string;\n}\n\nconst props = withDefaults(defineProps<GridMotionProps>(), {\n items: () => [],\n gradientColor: '#222222'\n});\n\nconst gridRef = useTemplateRef<HTMLElement>('gridRef');\nconst rowRefs = ref<HTMLElement[]>([]);\nconst mouseX = ref(window.innerWidth / 2);\n\nconst totalItems = 150;\nconst combinedItems = computed(() => {\n if (props.items.length === 0) {\n return [];\n }\n\n const repeatedItems = [];\n for (let i = 0; i < totalItems; i++) {\n repeatedItems.push(props.items[i % props.items.length]);\n }\n return repeatedItems;\n});\n\nfunction isImage(item: string) {\n return typeof item === 'string' && item.startsWith('http');\n}\n\nfunction isTag(item: string) {\n return typeof item === 'string' && item.startsWith('<') && item.endsWith('>');\n}\n\nonMounted(() => {\n gsap.ticker.lagSmoothing(0);\n\n const handleMouseMove = (e: MouseEvent) => {\n mouseX.value = e.clientX;\n };\n\n const updateMotion = () => {\n const maxMoveAmount = 300;\n const baseDuration = 0.8;\n const inertiaFactors = [0.6, 0.4, 0.3, 0.2];\n\n rowRefs.value.forEach((row, index) => {\n const direction = index % 2 === 0 ? 1 : -1;\n const moveAmount = ((mouseX.value / window.innerWidth) * maxMoveAmount - maxMoveAmount / 2) * direction;\n\n gsap.to(row, {\n x: moveAmount,\n duration: baseDuration + inertiaFactors[index % inertiaFactors.length],\n ease: 'power3.out',\n overwrite: 'auto'\n });\n });\n };\n\n const removeAnimation = gsap.ticker.add(updateMotion);\n window.addEventListener('mousemove', handleMouseMove);\n\n onBeforeUnmount(() => {\n window.removeEventListener('mousemove', handleMouseMove);\n removeAnimation();\n });\n});\n</script>\n\n<template>\n <div ref=\"gridRef\" class=\"w-full h-full overflow-hidden\">\n <section\n class=\"relative flex justify-center items-center w-full h-screen overflow-hidden\"\n :style=\"{\n background: `radial-gradient(circle, ${gradientColor} 0%, transparent 100%)`,\n backgroundPosition: 'center'\n }\"\n >\n <div class=\"z-[4] absolute inset-0 bg-[length:250px] pointer-events-none\"></div>\n\n <div class=\"z-[2] relative flex-none gap-4 grid grid-cols-1 w-[150vw] h-[150vh] rotate-[-15deg] origin-center\">\n <div\n v-for=\"rowIndex in 10\"\n :key=\"rowIndex\"\n class=\"gap-4 flex\"\n :style=\"{ willChange: 'transform, filter' }\"\n ref=\"rowRefs\"\n >\n <div\n v-for=\"itemIndex in 15\"\n :key=\"itemIndex\"\n class=\"relative h-[250px] min-w-[300px] flex-shrink-0\"\n v-show=\"combinedItems[(rowIndex - 1) * 15 + (itemIndex - 1)]\"\n >\n <div\n class=\"relative flex justify-center items-center bg-[#111] rounded-[10px] w-full h-full overflow-hidden text-[1.5rem] text-white\"\n >\n <div\n v-if=\"isImage(combinedItems[(rowIndex - 1) * 15 + (itemIndex - 1)])\"\n class=\"top-0 left-0 absolute bg-cover bg-center w-full h-full\"\n :style=\"{\n backgroundImage: `url(${combinedItems[(rowIndex - 1) * 15 + (itemIndex - 1)]})`\n }\"\n ></div>\n\n <div\n v-else-if=\"isTag(combinedItems[(rowIndex - 1) * 15 + (itemIndex - 1)])\"\n class=\"z-[2] p-4 text-center\"\n v-html=\"combinedItems[(rowIndex - 1) * 15 + (itemIndex - 1)]\"\n ></div>\n\n <div v-else class=\"z-[1] p-4 text-center\">\n {{ combinedItems[(rowIndex - 1) * 15 + (itemIndex - 1)] }}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"top-0 left-0 relative w-full h-full pointer-events-none\"></div>\n </section>\n </div>\n</template>\n","path":"GridMotion/GridMotion.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[{"ecosystem":"js","name":"gsap","version":"^3.13.0"}],"devDependencies":[],"categories":["Backgrounds"]} |