Add component for automatic carousel with fading animation
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 402 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 865 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 954 KiB |
@@ -0,0 +1,79 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import styled, { keyframes, Keyframes } from "styled-components";
|
||||
|
||||
interface CrossFadeImagesProps {
|
||||
images: string[];
|
||||
width: number | string;
|
||||
height: number | string;
|
||||
}
|
||||
|
||||
const SINGLE_IMAGE_PRESENTATION_TIME = 5;
|
||||
const SINGLE_CROSSFADE_TIME = 1;
|
||||
const SINGLE_IMAGE_TIME = SINGLE_IMAGE_PRESENTATION_TIME + SINGLE_CROSSFADE_TIME;
|
||||
|
||||
const AnimatedImage = styled(Image)<{ layout: "fill"; $delay: number }>`
|
||||
animation-delay: ${(p) => p.$delay}s;
|
||||
`;
|
||||
|
||||
const Container = styled.div<{ $animation: Keyframes; $duration: number; }>`
|
||||
position: relative;
|
||||
& > div {
|
||||
position: absolute !important;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
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> = ({
|
||||
images,
|
||||
}) => {
|
||||
const len = images.length;
|
||||
const TOTAL_TIME = SINGLE_IMAGE_TIME * len;
|
||||
|
||||
const animation = keyframes`
|
||||
0% {
|
||||
opacity:1;
|
||||
}
|
||||
${(SINGLE_IMAGE_PRESENTATION_TIME / TOTAL_TIME) * 100}% {
|
||||
opacity:1;
|
||||
}
|
||||
${(1 / len) * 100}% {
|
||||
opacity:0;
|
||||
}
|
||||
${100 - ((SINGLE_CROSSFADE_TIME / 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) => (
|
||||
<AnimatedImage
|
||||
key={image}
|
||||
src={image}
|
||||
objectFit="cover"
|
||||
layout="fill"
|
||||
$delay={delays[idx]}
|
||||
/>
|
||||
)) }
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default CrossFadeImages;
|
||||
@@ -9,3 +9,4 @@ export { default as FullWidthSection } from "./Sections/FullWidthSection";
|
||||
export { default as InfoBox } from "./InfoBox";
|
||||
export { default as Accordion } from "./Accordion/Accordion";
|
||||
export { default as Link } from "./Link";
|
||||
export { default as CrossFadeImages } from "./CrossFadeImages";
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Event } from "@models/Event";
|
||||
import { Post } from "@models/Feed";
|
||||
|
||||
import {
|
||||
Divider, CTASection, TextSection, Link,
|
||||
Divider, CTASection, TextSection, Link, CrossFadeImages,
|
||||
} from "@components/index";
|
||||
import ActualPageHero from "./ActualPageHero";
|
||||
import EventCalendar from "./EventCalendar";
|
||||
@@ -23,9 +23,12 @@ const Gallery = styled.div`
|
||||
|
||||
@media screen and (max-width: ${breakpoints.mobile}) {
|
||||
flex-flow: column;
|
||||
& > div {
|
||||
min-height: 100vw;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
& > div {
|
||||
flex: 1 0;
|
||||
}
|
||||
`;
|
||||
@@ -49,7 +52,18 @@ const ActualPageView: React.FC<ActualPageViewProps> = ({ events, feed }) => (
|
||||
</CTASection>
|
||||
|
||||
<Gallery>
|
||||
<Image src="https://placehold.it/400x400" alt="TODO" layout="responsive" objectFit="cover" width={400} height={400} />
|
||||
{/* <Image src="https://placehold.it/400x400" alt="TODO" layout="responsive" objectFit="cover" width={400} height={400} /> */}
|
||||
<CrossFadeImages
|
||||
images={[
|
||||
"/img/koydenveto-jani-mannonen-miika-koskela-17.jpg",
|
||||
"/img/koydenveto-jani-mannonen-miika-koskela-28.jpg",
|
||||
"/img/koydenveto-jani-mannonen-miika-koskela-78.jpg",
|
||||
"/img/Varaslahto2020-AinoSuomi-73.jpg",
|
||||
"/img/wappusitsit-jani-mannonen-29.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
/>
|
||||
<Image src="https://placehold.it/400x400" alt="TODO" layout="responsive" objectFit="cover" width={400} height={400} />
|
||||
<Image src="https://placehold.it/400x400" alt="TODO" layout="responsive" objectFit="cover" width={400} height={400} />
|
||||
</Gallery>
|
||||
|
||||
Reference in New Issue
Block a user