refactor: Логика координат точки на круге вынесена в отельную функцию, исправлены стили

This commit is contained in:
Ilia Mashkov
2025-11-20 16:07:18 +03:00
parent b84acfc3e7
commit c970d9c6d0
3 changed files with 34 additions and 46 deletions

View File

@@ -6,7 +6,7 @@
--color-bg: #F4F5F9; --color-bg: #F4F5F9;
--color-border: rgb(66 86 122 / 10%); --color-border: rgb(66 86 122 / 10%);
--color-blue: #3877EE; --color-blue: #3877EE;
--color-white: #FFFFFF; --color-white: #FFF;
// Градиенты // Градиенты
--gradient-primary: linear-gradient(to right, #3877EE, #EF5DA8); --gradient-primary: linear-gradient(to right, #3877EE, #EF5DA8);

View File

@@ -1,6 +1,4 @@
.circleContainer { .circleContainer {
$border-color: var(--color-primary);
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
@@ -8,7 +6,7 @@
width: calc(var(--circle-radius, 265px) * 2); width: calc(var(--circle-radius, 265px) * 2);
height: calc(var(--circle-radius, 265px) * 2); height: calc(var(--circle-radius, 265px) * 2);
border: 1px solid rgb($border-color / 20%); border: 1px solid rgba(#42567A, 0.2);
border-radius: 50%; border-radius: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
@@ -17,46 +15,48 @@
.point { .point {
position: absolute; position: absolute;
width: 6px; width: 56px;
height: 6px; height: 56px;
margin-top: -3px; margin-top: -28px;
margin-left: -3px; margin-left: -28px;
border: 25px solid transparent;
border-radius: 50%;
background: var(--color-text);
background-clip: content-box;
cursor: pointer; cursor: pointer;
background: var(--color-text); transform-origin: center;
border-radius: 50%;
transition: all 0.3s ease; transition: all 0.3s ease;
transform-origin: center;
&:hover, &:hover,
&.active { &.active {
z-index: 10; z-index: 10;
display: flex; display: flex;
align-items: center;
justify-content: center; justify-content: center;
align-items: center;
width: 56px; border: 1px solid rgba(#303E58, 0.5);
height: 56px;
margin-top: -28px;
margin-left: -28px;
border: 1px solid rgb(48 62 88 / 50%);
background: #F4F5F9; background: #F4F5F9;
}
.label { background-clip: padding-box;
display: none;
font-size: 20px;
color: var(--color-text);
} }
&:hover .label, &:hover .label,
&.active .label { &.active .label {
display: block; display: block;
} }
.label {
display: none;
color: var(--color-text);
font-size: 20px;
}
} }

View File

@@ -8,17 +8,13 @@
* Поддерживает клик по точкам для переключения периодов. * Поддерживает клик по точкам для переключения периодов.
*/ */
import classNames from 'classnames'
import gsap from 'gsap' import gsap from 'gsap'
import { memo, useCallback, useEffect, useMemo, useRef } from 'react' import { memo, useCallback, useEffect, useMemo, useRef } from 'react'
import styles from './CircleTimeline.module.scss' import styles from './CircleTimeline.module.scss'
import { import { calculateCoordinates } from '../../lib/utils/calculateCoordinates/calculateCoordinates'
ANIMATION_DURATION, import { ANIMATION_DURATION, ANIMATION_EASE } from '../../model'
ANIMATION_EASE,
CIRCLE_RADIUS,
FULL_CIRCLE_DEGREES,
HALF_CIRCLE_DEGREES,
} from '../../model'
import type { TimePeriod } from '@/entities/TimePeriod' import type { TimePeriod } from '@/entities/TimePeriod'
@@ -90,7 +86,7 @@ export const CircleTimeline = memo(function CircleTimeline({
if (point) { if (point) {
gsap.to(point, { gsap.to(point, {
rotation: -rotation, rotation: -rotation,
duration: ANIMATION_DURATION, duration: 0,
ease: ANIMATION_EASE, ease: ANIMATION_EASE,
}) })
} }
@@ -102,19 +98,9 @@ export const CircleTimeline = memo(function CircleTimeline({
* Пересчитывается только при изменении количества периодов * Пересчитывается только при изменении количества периодов
*/ */
const pointPositions = useMemo(() => { const pointPositions = useMemo(() => {
return periods.map((_, index) => { return periods.map((_, index, array) =>
// Угол для текущей точки (в градусах) calculateCoordinates(array.length, index)
const angle = (FULL_CIRCLE_DEGREES / periods.length) * index )
// Конвертация в радианы для тригонометрических функций
const radian = (angle * Math.PI) / HALF_CIRCLE_DEGREES
// Вычисление координат на круге
const x = CIRCLE_RADIUS * Math.cos(radian)
const y = CIRCLE_RADIUS * Math.sin(radian)
return { x, y }
})
}, [periods]) }, [periods])
/** /**
@@ -139,7 +125,9 @@ export const CircleTimeline = memo(function CircleTimeline({
ref={(el) => { ref={(el) => {
pointsRef.current[index] = el pointsRef.current[index] = el
}} }}
className={`${styles.point} ${index === activeIndex ? styles.active : ''}`} className={classNames(styles.point, {
[styles.active]: index === activeIndex,
})}
style={{ style={{
left: `calc(50% + ${x}px)`, left: `calc(50% + ${x}px)`,
top: `calc(50% + ${y}px)`, top: `calc(50% + ${y}px)`,