refactor: Переработка компонентов на использование хука useGSAP
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@gsap/react": "^2.1.2",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"gsap": "^3.13.0",
|
"gsap": "^3.13.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
|
|||||||
14
pnpm-lock.yaml
generated
14
pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@gsap/react':
|
||||||
|
specifier: ^2.1.2
|
||||||
|
version: 2.1.2(gsap@3.13.0)(react@19.2.0)
|
||||||
classnames:
|
classnames:
|
||||||
specifier: ^2.5.1
|
specifier: ^2.5.1
|
||||||
version: 2.5.1
|
version: 2.5.1
|
||||||
@@ -1111,6 +1114,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
|
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
|
'@gsap/react@2.1.2':
|
||||||
|
resolution: {integrity: sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw==}
|
||||||
|
peerDependencies:
|
||||||
|
gsap: ^3.12.5
|
||||||
|
react: '>=17'
|
||||||
|
|
||||||
'@humanfs/core@0.19.1':
|
'@humanfs/core@0.19.1':
|
||||||
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
|
||||||
engines: {node: '>=18.18.0'}
|
engines: {node: '>=18.18.0'}
|
||||||
@@ -6799,6 +6808,11 @@ snapshots:
|
|||||||
'@eslint/core': 0.17.0
|
'@eslint/core': 0.17.0
|
||||||
levn: 0.4.1
|
levn: 0.4.1
|
||||||
|
|
||||||
|
'@gsap/react@2.1.2(gsap@3.13.0)(react@19.2.0)':
|
||||||
|
dependencies:
|
||||||
|
gsap: 3.13.0
|
||||||
|
react: 19.2.0
|
||||||
|
|
||||||
'@humanfs/core@0.19.1': {}
|
'@humanfs/core@0.19.1': {}
|
||||||
|
|
||||||
'@humanfs/node@0.16.7':
|
'@humanfs/node@0.16.7':
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
* Поддерживает клик по точкам для переключения периодов.
|
* Поддерживает клик по точкам для переключения периодов.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { useGSAP } from '@gsap/react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { gsap } from 'gsap'
|
import { gsap } from 'gsap'
|
||||||
import { memo, useCallback, useEffect, useMemo, useRef } from 'react'
|
import { memo, useCallback, useMemo, useRef } from 'react'
|
||||||
|
|
||||||
import styles from './CircleTimeline.module.scss'
|
import styles from './CircleTimeline.module.scss'
|
||||||
import { calculateCoordinates } from '../../lib/utils/calculateCoordinates/calculateCoordinates'
|
import { calculateCoordinates } from '../../lib/utils/calculateCoordinates/calculateCoordinates'
|
||||||
@@ -71,10 +72,11 @@ export const CircleTimeline = memo(function CircleTimeline({
|
|||||||
const titlesRef = useRef<(HTMLSpanElement | null)[]>([])
|
const titlesRef = useRef<(HTMLSpanElement | null)[]>([])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Эффект для анимации поворота круга и контр-поворота точек
|
* Анимация поворота круга и контр-поворота точек
|
||||||
* Запускается при изменении rotation
|
* Использует useGSAP hook для автоматической очистки анимаций
|
||||||
*/
|
*/
|
||||||
useEffect(() => {
|
useGSAP(
|
||||||
|
() => {
|
||||||
// Анимация поворота контейнера круга
|
// Анимация поворота контейнера круга
|
||||||
if (circleRef.current) {
|
if (circleRef.current) {
|
||||||
gsap.to(circleRef.current, {
|
gsap.to(circleRef.current, {
|
||||||
@@ -96,7 +98,7 @@ export const CircleTimeline = memo(function CircleTimeline({
|
|||||||
// Анимация заголовка
|
// Анимация заголовка
|
||||||
const title = titlesRef.current[index]
|
const title = titlesRef.current[index]
|
||||||
if (title) {
|
if (title) {
|
||||||
// Сбрасываем предыдущие анимации для этого элемента
|
// Останавливаем предыдущие анимации для предотвращения конфликтов
|
||||||
gsap.killTweensOf(title)
|
gsap.killTweensOf(title)
|
||||||
|
|
||||||
if (index === activeIndex) {
|
if (index === activeIndex) {
|
||||||
@@ -116,7 +118,9 @@ export const CircleTimeline = memo(function CircleTimeline({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [rotation, activeIndex])
|
},
|
||||||
|
{ dependencies: [rotation, activeIndex] }
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Мемоизированный расчет позиций точек на круге
|
* Мемоизированный расчет позиций точек на круге
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
* Отображает список исторических событий в виде слайдера
|
* Отображает список исторических событий в виде слайдера
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { useGSAP } from '@gsap/react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { gsap } from 'gsap'
|
import { gsap } from 'gsap'
|
||||||
import { memo, useEffect, useRef, useState } from 'react'
|
import { memo, useRef, useState } from 'react'
|
||||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||||
|
|
||||||
import 'swiper/css'
|
import 'swiper/css'
|
||||||
@@ -45,7 +46,7 @@ export interface EventsCarouselProps {
|
|||||||
*
|
*
|
||||||
* Использует Swiper для создания слайдера с кастомной навигацией.
|
* Использует Swiper для создания слайдера с кастомной навигацией.
|
||||||
* Поддерживает адаптивное количество слайдов на разных размерах экрана.
|
* Поддерживает адаптивное количество слайдов на разных размерах экрана.
|
||||||
* Анимирует появление/исчезновение с помощью GSAP.
|
* Анимирует появление/исчезновение с помощью GSAP useGSAP hook.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```tsx
|
* ```tsx
|
||||||
@@ -62,13 +63,11 @@ export const EventsCarousel = memo(
|
|||||||
const [isEnd, setIsEnd] = useState(false)
|
const [isEnd, setIsEnd] = useState(false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Эффект для анимации появления/исчезновения карусели
|
* Анимация появления/исчезновения карусели
|
||||||
* Использует GSAP для плавной анимации opacity и y-позиции
|
* Использует useGSAP hook для автоматической очистки анимаций
|
||||||
*/
|
*/
|
||||||
useEffect(() => {
|
useGSAP(
|
||||||
if (!containerRef.current) return
|
() => {
|
||||||
|
|
||||||
const ctx = gsap.context(() => {
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
gsap.fromTo(
|
gsap.fromTo(
|
||||||
containerRef.current,
|
containerRef.current,
|
||||||
@@ -86,10 +85,9 @@ export const EventsCarousel = memo(
|
|||||||
duration: HIDE_DURATION,
|
duration: HIDE_DURATION,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, containerRef)
|
},
|
||||||
|
{ scope: containerRef, dependencies: [visible, events] }
|
||||||
return () => ctx.revert()
|
)
|
||||||
}, [visible, events])
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Обработчик инициализации Swiper
|
* Обработчик инициализации Swiper
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Главный компонент временной шкалы с круговой диаграммой и каруселью событий
|
* Главный компонент временной шкалы с круговой диаграммой и каруселью событий
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { useGSAP } from '@gsap/react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { gsap } from 'gsap'
|
import { gsap } from 'gsap'
|
||||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
@@ -21,7 +22,7 @@ import { EventsCarousel } from '../EventsCarousel/EventsCarousel'
|
|||||||
*
|
*
|
||||||
* Отображает исторические периоды на круговой диаграмме с возможностью
|
* Отображает исторические периоды на круговой диаграмме с возможностью
|
||||||
* переключения между ними. Для каждого периода показывается карусель событий.
|
* переключения между ними. Для каждого периода показывается карусель событий.
|
||||||
* Центральные даты анимируются при смене периода с помощью GSAP.
|
* Центральные даты анимируются при смене периода с помощью GSAP useGSAP hook.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```tsx
|
* ```tsx
|
||||||
@@ -66,13 +67,11 @@ export const TimeFrameSlider = memo(() => {
|
|||||||
}, [activePeriod, anglePerPoint])
|
}, [activePeriod, anglePerPoint])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Анимация центральных дат с использованием GSAP
|
* Анимация центральных дат с использованием GSAP useGSAP hook
|
||||||
* Плавно изменяет числа при смене периода
|
* Плавно изменяет числа при смене периода
|
||||||
*/
|
*/
|
||||||
useEffect(() => {
|
useGSAP(
|
||||||
if (!containerRef.current) return
|
() => {
|
||||||
|
|
||||||
const ctx = gsap.context(() => {
|
|
||||||
if (startYearRef.current) {
|
if (startYearRef.current) {
|
||||||
gsap.fromTo(
|
gsap.fromTo(
|
||||||
startYearRef.current,
|
startYearRef.current,
|
||||||
@@ -109,10 +108,12 @@ export const TimeFrameSlider = memo(() => {
|
|||||||
{ opacity: 1, visibility: 'visible', duration: 1 }
|
{ opacity: 1, visibility: 'visible', duration: 1 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}, containerRef)
|
},
|
||||||
|
{
|
||||||
return () => ctx.revert()
|
scope: containerRef,
|
||||||
}, [currentPeriod.yearFrom, currentPeriod.yearTo])
|
dependencies: [currentPeriod.yearFrom, currentPeriod.yearTo],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Переключение на предыдущий период
|
* Переключение на предыдущий период
|
||||||
|
|||||||
Reference in New Issue
Block a user