parent
26cbef8763
commit
dfd0d71b3b
@ -0,0 +1,9 @@ |
|||||||
|
import reduce from 'lodash/reduce' |
||||||
|
|
||||||
|
import type { Events } from 'requests' |
||||||
|
|
||||||
|
export const fullEpisodesDuration = (filters: Events) => reduce( |
||||||
|
filters, |
||||||
|
(acc, filter) => acc + (Number(filter.e) - Number(filter.s)), |
||||||
|
0, |
||||||
|
) |
||||||
@ -0,0 +1,72 @@ |
|||||||
|
import type { Dispatch, SetStateAction } from 'react' |
||||||
|
import { useEffect } from 'react' |
||||||
|
|
||||||
|
import isEmpty from 'lodash/isEmpty' |
||||||
|
|
||||||
|
import type { Events } from 'requests' |
||||||
|
|
||||||
|
import { fullEpisodesDuration } from './helpers' |
||||||
|
import { Svg, Circle } from './styled' |
||||||
|
|
||||||
|
export type TCircleAnimation = { |
||||||
|
plaingOrder: number, |
||||||
|
playedProgress: number, |
||||||
|
playing: boolean, |
||||||
|
ready: boolean, |
||||||
|
} |
||||||
|
|
||||||
|
export const initialCircleAnimation: TCircleAnimation = { |
||||||
|
plaingOrder: 0, |
||||||
|
playedProgress: 0, |
||||||
|
playing: false, |
||||||
|
ready: false, |
||||||
|
} |
||||||
|
|
||||||
|
type Props = { |
||||||
|
circleAnimation?: TCircleAnimation, |
||||||
|
filteredEvents: Events, |
||||||
|
setWatchAllEpisodesTimer: (showTimer: boolean) => void, |
||||||
|
} |
||||||
|
|
||||||
|
export type TSetCircleAnimation = Dispatch<SetStateAction<TCircleAnimation>> |
||||||
|
|
||||||
|
export const CircleAnimationBar = ({ |
||||||
|
circleAnimation, |
||||||
|
filteredEvents, |
||||||
|
setWatchAllEpisodesTimer, |
||||||
|
}: Props) => { |
||||||
|
const { |
||||||
|
plaingOrder, |
||||||
|
playedProgress, |
||||||
|
playing, |
||||||
|
ready, |
||||||
|
} = circleAnimation! |
||||||
|
const timeOfAllEpisodes = fullEpisodesDuration(filteredEvents) |
||||||
|
const remainingEvents = filteredEvents.slice(plaingOrder - 1) |
||||||
|
const fullTimeOfRemainingEpisodes = !isEmpty(remainingEvents) |
||||||
|
? fullEpisodesDuration(remainingEvents) |
||||||
|
: 0 |
||||||
|
const animationPause = !playing || !ready |
||||||
|
|
||||||
|
const currentAnimationTime = Math.round(fullTimeOfRemainingEpisodes - (playedProgress / 1000)) |
||||||
|
const currentEpisodesPercent = 100 - (100 / (timeOfAllEpisodes / currentAnimationTime)) |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (currentEpisodesPercent >= 100) { |
||||||
|
setWatchAllEpisodesTimer(false) |
||||||
|
} |
||||||
|
}, [currentEpisodesPercent, setWatchAllEpisodesTimer]) |
||||||
|
|
||||||
|
return ( |
||||||
|
<Svg> |
||||||
|
<Circle |
||||||
|
cx='50%' |
||||||
|
cy='50%' |
||||||
|
r='50%' |
||||||
|
currentAnimationTime={currentAnimationTime} |
||||||
|
animationPause={animationPause} |
||||||
|
currentEpisodesPercent={currentEpisodesPercent} |
||||||
|
/> |
||||||
|
</Svg> |
||||||
|
) |
||||||
|
} |
||||||
@ -0,0 +1,43 @@ |
|||||||
|
import styled, { keyframes } from 'styled-components/macro' |
||||||
|
|
||||||
|
type TCircle = { |
||||||
|
animationPause?: boolean, |
||||||
|
currentAnimationTime: number, |
||||||
|
currentEpisodesPercent: number, |
||||||
|
} |
||||||
|
|
||||||
|
const strokeDashOffset = 43.5 |
||||||
|
|
||||||
|
const clockAnimation = (currentEpisodesPercent?: number) => keyframes` |
||||||
|
from { |
||||||
|
stroke-dashoffset: ${currentEpisodesPercent}; |
||||||
|
} |
||||||
|
to { |
||||||
|
stroke-dashoffset: 0; |
||||||
|
} |
||||||
|
` |
||||||
|
|
||||||
|
export const Svg = styled.svg` |
||||||
|
background-color: #5EB2FF; |
||||||
|
width: 14px; |
||||||
|
height: 14px; |
||||||
|
position: relative; |
||||||
|
border-radius: 50%; |
||||||
|
` |
||||||
|
|
||||||
|
export const Circle = styled.circle<TCircle>` |
||||||
|
fill: transparent; |
||||||
|
stroke: white; |
||||||
|
stroke-width: 14px; |
||||||
|
stroke-dasharray: ${strokeDashOffset}; |
||||||
|
stroke-dashoffset: ${strokeDashOffset}; |
||||||
|
transform: rotate(-90deg); |
||||||
|
transform-origin: center; |
||||||
|
animation-name: ${({ currentEpisodesPercent }) => ( |
||||||
|
clockAnimation(strokeDashOffset - (strokeDashOffset * currentEpisodesPercent / 100)) |
||||||
|
)}; |
||||||
|
animation-duration: ${({ currentAnimationTime }) => `${currentAnimationTime}s`}; |
||||||
|
animation-play-state: ${({ animationPause }) => (animationPause ? 'paused' : 'running')}; |
||||||
|
animation-timing-function: linear; |
||||||
|
animation-fill-mode: forwards; |
||||||
|
` |
||||||
Loading…
Reference in new issue