109 lines
2.7 KiB
Plaintext
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> |