mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 14:39:30 -07:00
Refactor GridMotion component and demo for improved item handling and styling
This commit is contained in:
@@ -6,40 +6,16 @@ export const gridMotion: CodeObject = {
|
|||||||
installation: `npm i gsap`,
|
installation: `npm i gsap`,
|
||||||
usage: `<template>
|
usage: `<template>
|
||||||
<GridMotion
|
<GridMotion
|
||||||
:items="items"
|
:items="images"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import GridMotion from "./GridMotion.vue";
|
import GridMotion from "./GridMotion.vue";
|
||||||
|
|
||||||
const items = [
|
const imageUrl = 'https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D';
|
||||||
"Item 1",
|
const numberOfImages = 30;
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
const images = Array.from({ length: numberOfImages }, () => imageUrl);
|
||||||
"https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
"Item 2",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"Item 4",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
"Item 5",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"Item 7",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
"Item 8",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"Item 10",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
"Item 11",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"Item 13",
|
|
||||||
`<div key='item-1'>Custom Content</div>`,
|
|
||||||
"https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
|
|
||||||
"Item 14",
|
|
||||||
// Add more items as needed
|
|
||||||
];
|
|
||||||
</script>`,
|
</script>`,
|
||||||
code,
|
code,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,16 +9,25 @@ interface GridMotionProps {
|
|||||||
|
|
||||||
const props = withDefaults(defineProps<GridMotionProps>(), {
|
const props = withDefaults(defineProps<GridMotionProps>(), {
|
||||||
items: () => [],
|
items: () => [],
|
||||||
gradientColor: 'black'
|
gradientColor: '#222222'
|
||||||
});
|
});
|
||||||
|
|
||||||
const gridRef = ref<HTMLElement | null>(null);
|
const gridRef = ref<HTMLElement | null>(null);
|
||||||
const rowRefs = ref<HTMLElement[]>([]);
|
const rowRefs = ref<HTMLElement[]>([]);
|
||||||
const mouseX = ref(window.innerWidth / 2);
|
const mouseX = ref(window.innerWidth / 2);
|
||||||
|
|
||||||
const totalItems = 28;
|
const totalItems = 70;
|
||||||
const defaultItems = Array.from({ length: totalItems }, (_, i) => `Item ${i + 1}`);
|
const combinedItems = computed(() => {
|
||||||
const combinedItems = computed(() => (props.items.length > 0 ? props.items.slice(0, totalItems) : defaultItems));
|
if (props.items.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const repeatedItems = [];
|
||||||
|
for (let i = 0; i < totalItems; i++) {
|
||||||
|
repeatedItems.push(props.items[i % props.items.length]);
|
||||||
|
}
|
||||||
|
return repeatedItems;
|
||||||
|
});
|
||||||
|
|
||||||
function isImage(item: string) {
|
function isImage(item: string) {
|
||||||
return typeof item === 'string' && item.startsWith('http');
|
return typeof item === 'string' && item.startsWith('http');
|
||||||
@@ -68,22 +77,26 @@ onMounted(() => {
|
|||||||
<section
|
<section
|
||||||
class="relative flex justify-center items-center w-full h-screen overflow-hidden"
|
class="relative flex justify-center items-center w-full h-screen overflow-hidden"
|
||||||
:style="{
|
:style="{
|
||||||
background: `radial-gradient(circle, ${gradientColor} 0%, transparent 100%)`
|
background: `radial-gradient(circle, ${gradientColor} 0%, transparent 100%)`,
|
||||||
|
backgroundPosition: 'center'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="z-[4] absolute inset-0 bg-[length:250px] pointer-events-none"></div>
|
<div class="z-[4] absolute inset-0 bg-[length:250px] pointer-events-none"></div>
|
||||||
|
|
||||||
|
<div class="z-[2] relative flex-none gap-4 grid grid-cols-1 w-[150vw] h-[150vh] rotate-[-15deg] origin-center">
|
||||||
<div
|
<div
|
||||||
class="z-[2] relative flex-none gap-4 grid grid-cols-1 grid-rows-4 w-[150vw] h-[150vh] rotate-[-15deg] origin-center"
|
v-for="rowIndex in 10"
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-for="rowIndex in 4"
|
|
||||||
:key="rowIndex"
|
:key="rowIndex"
|
||||||
class="gap-4 grid grid-cols-7"
|
class="gap-4 grid grid-cols-7"
|
||||||
:style="{ willChange: 'transform, filter' }"
|
:style="{ willChange: 'transform, filter' }"
|
||||||
ref="rowRefs"
|
ref="rowRefs"
|
||||||
>
|
>
|
||||||
<div v-for="itemIndex in 7" :key="itemIndex" class="relative">
|
<div
|
||||||
|
v-for="itemIndex in 7"
|
||||||
|
:key="itemIndex"
|
||||||
|
class="relative h-[200px]"
|
||||||
|
v-show="combinedItems[(rowIndex - 1) * 7 + (itemIndex - 1)]"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="relative flex justify-center items-center bg-[#111] rounded-[10px] w-full h-full overflow-hidden text-[1.5rem] text-white"
|
class="relative flex justify-center items-center bg-[#111] rounded-[10px] w-full h-full overflow-hidden text-[1.5rem] text-white"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,18 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<TabbedLayout>
|
<TabbedLayout>
|
||||||
<template #preview>
|
<template #preview>
|
||||||
<h2 className="demo-title-extra">Images</h2>
|
<div class="demo-container h-[600px]">
|
||||||
|
|
||||||
<div class="relative py-6 rounded-3xl overflow-hidden demo-container" style="height: 700px">
|
|
||||||
<GridMotion :items="images" />
|
<GridMotion :items="images" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 className="demo-title-extra">Custom Content</h2>
|
|
||||||
|
|
||||||
<div class="relative py-6 rounded-3xl overflow-hidden demo-container" style="height: 700px">
|
|
||||||
<GridMotion :items="items" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<PropTable :data="propData" />
|
<PropTable :data="propData" />
|
||||||
|
|
||||||
<Dependencies :dependency-list="['gsap']" />
|
<Dependencies :dependency-list="['gsap']" />
|
||||||
@@ -53,34 +45,14 @@ const propData = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const imageUrl =
|
const imageUrl =
|
||||||
'https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D';
|
'https://images.unsplash.com/photo-1748370987492-eb390a61dcda?q=80&w=1364&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D';
|
||||||
const numberOfImages = 30;
|
const numberOfImages = 30;
|
||||||
const images = Array.from({ length: numberOfImages }, () => imageUrl);
|
const images = Array.from({ length: numberOfImages }, () => imageUrl);
|
||||||
|
|
||||||
const items = [
|
|
||||||
'Item 1',
|
|
||||||
`<div key="item-1">Custom Content</div>`,
|
|
||||||
'https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
||||||
'Item 2',
|
|
||||||
`<div key="item-2">Custom Content</div>`,
|
|
||||||
'Item 4',
|
|
||||||
`<div key="item-3">Custom Content</div>`,
|
|
||||||
'https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
||||||
'Item 5',
|
|
||||||
`<div key="item-4">Custom Content</div>`,
|
|
||||||
'Item 7',
|
|
||||||
`<div key="item-5">Custom Content</div>`,
|
|
||||||
'https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
||||||
'Item 8',
|
|
||||||
`<div key="item-6">Custom Content</div>`,
|
|
||||||
'Item 10',
|
|
||||||
`<div key="item-7">Custom Content</div>`,
|
|
||||||
'https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
||||||
'Item 11',
|
|
||||||
`<div key="item-8">Custom Content</div>`,
|
|
||||||
'Item 13',
|
|
||||||
`<div key="item-9">Custom Content</div>`,
|
|
||||||
'https://images.unsplash.com/photo-1723403804231-f4e9b515fe9d?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
||||||
'Item 14'
|
|
||||||
];
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.demo-container {
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user