practice_code/web/graduation/src/components/aceternity/AnimatedGallery.astro
2025-03-23 01:42:26 +08:00

109 lines
2.7 KiB
Plaintext

---
interface Image {
src: string;
alt: string;
width?: number;
height?: number;
}
interface Props {
images: Image[];
className?: string;
gap?: number;
direction?: 'left' | 'right';
speed?: 'slow' | 'normal' | 'fast';
}
const {
images,
className = "",
gap = 16,
direction = 'left',
speed = 'normal'
} = Astro.props;
// 计算速度
const getSpeed = () => {
switch(speed) {
case 'slow': return '60s';
case 'fast': return '20s';
default: return '40s';
}
};
const speedValue = getSpeed();
---
<div class={`animated-gallery overflow-hidden ${className}`}>
<div class="flex items-center w-full" style={`gap: ${gap}px;`}>
<!-- 复制两组图片,确保无缝循环 -->
<div
class="flex animated-slide"
style={`gap: ${gap}px; animation: scroll-${direction} ${speedValue} linear infinite;`}
>
{images.map(image => (
<div class="flex-shrink-0 rounded-lg overflow-hidden">
<div
class="bg-gray-300 dark:bg-gray-700 flex items-center justify-center"
style={`width: ${image.width || 300}px; height: ${image.height || 200}px;`}
>
<span class="text-gray-500 dark:text-gray-400">{image.alt}</span>
</div>
</div>
))}
</div>
<!-- 复制第二组,确保无缝循环 -->
<div
class="flex animated-slide"
style={`gap: ${gap}px; animation: scroll-${direction} ${speedValue} linear infinite;`}
>
{images.map(image => (
<div class="flex-shrink-0 rounded-lg overflow-hidden">
<div
class="bg-gray-300 dark:bg-gray-700 flex items-center justify-center"
style={`width: ${image.width || 300}px; height: ${image.height || 200}px;`}
>
<span class="text-gray-500 dark:text-gray-400">{image.alt}</span>
</div>
</div>
))}
</div>
</div>
</div>
<style>
@keyframes scroll-left {
0% {
transform: translateX(0);
}
100% {
transform: translateX(calc(-100% - var(--gap, 16px)));
}
}
@keyframes scroll-right {
0% {
transform: translateX(calc(-100% - var(--gap, 16px)));
}
100% {
transform: translateX(0);
}
}
.animated-gallery:hover .animated-slide {
animation-play-state: paused;
}
</style>
<script>
// 动态计算间隙变量
document.addEventListener('DOMContentLoaded', () => {
const galleries = document.querySelectorAll('.animated-gallery');
galleries.forEach(gallery => {
const gap = gallery.querySelector('.flex')?.getAttribute('style')?.match(/gap: (\d+)px/)?.[1] || '16';
(gallery as HTMLElement).style.setProperty('--gap', `${gap}px`);
});
});
</script>