Files
web2.0-frontend/src/components/CrossFadeImages.tsx
T
Aarni Halinen c330a21f59 fix stylelint
2021-06-03 02:39:04 +03:00

90 lines
2.0 KiB
TypeScript

import React from "react";
import Image, { ImageProps } from "next/image";
import styled, { keyframes, Keyframes } from "styled-components";
interface CrossFadeImagesProps {
width: ImageProps["width"];
height: ImageProps["height"];
images: string[];
presentationTime: number;
fadeTime: number;
}
const AnimatedImage = styled(Image)<{ layout: string; $delay: number }>`
animation-delay: ${(p) => p.$delay}s;
`;
const Container = styled.div<{ $animation: Keyframes; $duration: number; }>`
display: flex;
flex-flow: row nowrap;
.not-first {
margin-left: -100%;
}
& > div {
box-sizing: border-box;
width: 100%;
flex: none;
img {
animation-name: ${(p) => p.$animation};
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: ${(p) => p.$duration}s;
}
}
`;
const CrossFadeImages: React.FC<CrossFadeImagesProps> = ({
width, height, images, presentationTime, fadeTime,
}) => {
const len = images.length;
const SINGLE_IMAGE_TIME = presentationTime + fadeTime;
const TOTAL_TIME = SINGLE_IMAGE_TIME * len;
const animation = keyframes`
0% {
opacity: 1;
}
${(presentationTime / TOTAL_TIME) * 100}% {
opacity: 1;
}
${(1 / len) * 100}% {
opacity: 0;
}
${100 - ((fadeTime / TOTAL_TIME) * 100)}% {
opacity: 0;
}
100% {
opacity: 1;
}
`;
const delays = images.map((_, idx) => idx * SINGLE_IMAGE_TIME).reverse();
return (
<Container
$animation={animation}
$duration={len * SINGLE_IMAGE_TIME}
>
{ images.map((image, idx) => (
<div key={idx} className={idx > 0 ? "not-first" : undefined}>
<AnimatedImage
key={image}
src={image}
objectFit="cover"
width={width}
height={height}
layout="responsive"
$delay={delays[idx]}
/>
</div>
))}
</Container>
);
};
export default CrossFadeImages;