You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
4.8 KiB
TypeScript

import { useRef } from 'react';
import styles from './citiesCard.module.scss';
import { Card } from '@/components/card';
import useLocale from '@/utils/useLocale';
import { LocalesMap } from '@/utils/useLocale';
import CityPolotskSmallEn from '@/assets/images/city-polotsk-small-en.svg';
import CityNovopolotskSmallEn from '@/assets/images/city-novopolotsk-small-en.svg';
import CityMiorySmallEn from '@/assets/images/city-miory-small-en.svg';
import CityBigEn from '@/assets/images/city-big-en.svg';
import CityPolotskSmallRu from '@/assets/images/city-polotsk-small-ru.svg';
import CityNovopolotskSmallRu from '@/assets/images/city-novopolotsk-small-ru.svg';
import CityMiorySmallRu from '@/assets/images/city-miory-small-ru.svg';
import CityBigRu from '@/assets/images/city-big-ru.svg';
import Mask from '@/assets/images/cities-star-mask.svg';
import ridebusImage from '@/assets/images/cities-backdrop.jpg';
import Image from 'next/image';
import useFrame from '@/utils/useFrame';
import useScroll from '@/utils/useScroll';
import { useRouter } from 'next/router';
import useMediaQuery from '@/utils/useMediaQuery';
const locales: LocalesMap = {
ru: {
title: 'Поддержка нескольких городов',
description:
'Поддерживаются города Полоцк и Новополоцк, но мы планируем добавлять расписание общественного транспорта и для других городов Беларуси',
},
en: {
title: 'Multi-city support',
description:
'The cities of Polotsk and Novopolotsk are supported, but we plan to add public transportation schedules for other cities of Belarus as well',
},
};
function SmallCitiesLine() {
const router = useRouter();
const rootRef = useRef<HTMLDivElement>(null);
const breakpoint800 = useMediaQuery('(max-width: 800px)');
const cityWidth = breakpoint800 ? 170 : 220;
const swapWidth = cityWidth * 2;
useScroll((scrollY, delta, time) => {
const offset = -(scrollY / 6) - (time / 30);
if (rootRef.current) {
rootRef.current.style.transform = `rotate(3deg) translate3D(${offset % swapWidth + cityWidth * 2}px, 0px, 0px)`;
}
}, {}, [cityWidth]);
const CityPolotsk = router.locale === 'ru' ? CityPolotskSmallRu : CityPolotskSmallEn;
const CityNovopolotsk = router.locale === 'ru' ? CityNovopolotskSmallRu : CityNovopolotskSmallEn;
const CityMiory = router.locale === 'ru' ? CityMiorySmallRu : CityMiorySmallEn;
return (
<div ref={rootRef} className={styles.smallCitiesLine}>
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
</div>
);
}
function BigCitiesLine() {
const router = useRouter();
const rootRef = useRef<HTMLDivElement>(null);
const breakpoint800 = useMediaQuery('(max-width: 800px)');
const cityWidth = (breakpoint800 ? 200 : 260) + 9;
const swapWidth = cityWidth * 1;
useScroll((scrollY, delta, time) => {
const offset = (scrollY / 6) + (time / 30);
if (rootRef.current) {
rootRef.current.style.transform = `rotate(356deg) translate3D(${offset % swapWidth * 3}px, 0px, 0px)`;
}
}, {}, [cityWidth]);
const CityPolotsk = router.locale === 'ru' ? CityPolotskSmallRu : CityPolotskSmallEn;
const CityNovopolotsk = router.locale === 'ru' ? CityNovopolotskSmallRu : CityNovopolotskSmallEn;
const CityMiory = router.locale === 'ru' ? CityMiorySmallRu : CityMiorySmallEn;
return (
<div ref={rootRef} className={styles.bigCitiesLine}>
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
<CityPolotsk />
<CityNovopolotsk />
<CityMiory />
</div>
);
}
export function CitiesCard() {
const t = useLocale(locales);
const ridebusImageMask = useRef<HTMLDivElement>(null);
const ridebusImageRef = useRef<HTMLDivElement>(null);
useFrame((delta, time) => {
if (ridebusImageMask.current) {
ridebusImageMask.current.style.transform = `rotate(${(time * 0.005) % 360}deg) translate3D(0px, 0px, 0px)`;
}
});
return (
<Card
className={styles.card}
title={t('title')}
subtitle={t('description')}
backdropOnText
classes={{ subtitle: styles.description, title: styles.title }}
>
<div className={styles.mockupPhoneContainer}>
<div className={styles.ridebusImageMask}
ref={ridebusImageMask}>
<Mask />
</div>
<BigCitiesLine />
</div>
</Card>
);
}