From 645d792464b8ebe648ae88036149f80566c0fe10 Mon Sep 17 00:00:00 2001 From: Ricardo Casares Date: Sat, 31 Oct 2020 02:18:18 +0100 Subject: [PATCH] feat: logo has some rythm --- src/components/Header/index.tsx | 5 +++-- src/components/Logo/index.tsx | 21 +++++++++++++++++ src/lib/context/audio.tsx | 7 +++++- src/lib/hooks/useFrequency.ts | 40 +++++++++++++++++++++++++++++++++ src/lib/utils.ts | 8 +++++++ 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/components/Logo/index.tsx create mode 100644 src/lib/hooks/useFrequency.ts diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index e3c742ca..1dc64ccf 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,12 +1,13 @@ import Link from "next/link"; -import { HeartFill, Radio, Search, Sliders } from "@geist-ui/react-icons"; +import { Logo } from "@/components/Logo"; +import { HeartFill, Search, Sliders } from "@geist-ui/react-icons"; import { Container, Navigation } from "./style"; export const Header = () => ( - + diff --git a/src/components/Logo/index.tsx b/src/components/Logo/index.tsx new file mode 100644 index 00000000..dcc5dcb6 --- /dev/null +++ b/src/components/Logo/index.tsx @@ -0,0 +1,21 @@ +import styled from "@emotion/styled"; +import { Radio } from "@geist-ui/react-icons"; +import { useFrequency } from "@/lib/hooks/useFrequency"; +import { mapValueToRange } from "@/lib/utils"; + +type Icon = { + alpha: number; +}; + +const Icon = styled(Radio)` + path { + color: ${({ alpha }) => `rgba(0, 112, 243, ${alpha})`}; + } +`; + +export const Logo = () => { + const freq = useFrequency(); + const alpha = mapValueToRange(freq, [0, 255], [0, 1]); + + return ; +}; diff --git a/src/lib/context/audio.tsx b/src/lib/context/audio.tsx index 6fbf3f74..ff87f1ca 100644 --- a/src/lib/context/audio.tsx +++ b/src/lib/context/audio.tsx @@ -9,7 +9,12 @@ export const AudioElementProvider = ({ children }) => { return ( {children} - ); }; diff --git a/src/lib/hooks/useFrequency.ts b/src/lib/hooks/useFrequency.ts new file mode 100644 index 00000000..6f1edfbc --- /dev/null +++ b/src/lib/hooks/useFrequency.ts @@ -0,0 +1,40 @@ +import { useState, useContext, useEffect } from "react"; +import { AudioElementContext } from "@/lib/context/audio"; + +export function useFrequency() { + const audio = useContext(AudioElementContext); + const [state, setState] = useState(100); + + useEffect(() => { + const ctx = new AudioContext(); + const analyser = ctx.createAnalyser(); + const source = ctx.createMediaElementSource(audio.current); + analyser.fftSize = 64; + analyser.smoothingTimeConstant = 0.1; + + const frequencyData = new Uint8Array(analyser.frequencyBinCount); + + const update = () => { + analyser.getByteFrequencyData(frequencyData); + setState(frequencyData[1]); + return requestAnimationFrame(update); + }; + + const frame = update(); + + const onCanPlay = () => { + source.connect(ctx.destination); + source.connect(analyser); + ctx.resume(); + }; + + audio.current.addEventListener("canplay", onCanPlay); + + return () => { + cancelAnimationFrame(frame); + audio.current.removeEventListener("canplay", onCanPlay); + }; + }, []); + + return state; +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 31ded1a8..b48ddab8 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -5,3 +5,11 @@ export const localesMap = { pl: "Polski", ru: "Русский", }; + +export function mapValueToRange( + n: number, + [a, b]: [number, number], + [x, y]: [number, number] +) { + return ((n - a) * (y - x)) / (b - a) + x; +}