mirror of
https://github.com/cupcakearmy/old.nicco.io.git
synced 2025-09-05 18:20:46 +00:00
migrated to nextjs
This commit is contained in:
42
components/AnimatedBackground.tsx
Normal file
42
components/AnimatedBackground.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
import { Duration } from '../utils/config'
|
||||
import { GoldenRatio, Rand } from '../utils/utils'
|
||||
import '../styles/AnimatedBackground.styl'
|
||||
|
||||
|
||||
|
||||
type Color = [number, number, number]
|
||||
|
||||
const getRandomColor = () => [Rand(0, 255), Rand(70, 90), Rand(80, 90)] as Color
|
||||
const colorToString = ([h, s, l]: Color) => `hsl(${h}, ${s}%, ${l}%)` as string
|
||||
const valuesToGradient = (dir: number, from: Color, to: Color) => `linear-gradient(${dir}deg, ${colorToString(from)}, ${colorToString(to)})` as string
|
||||
|
||||
const AnimatedBackground: React.FC = () => {
|
||||
|
||||
const [start, setStart] = useState<Color>([255, 255, 255])
|
||||
const [end, setEnd] = useState<Color>([255, 255, 255])
|
||||
const [direction, setDirection] = useState<number>(0)
|
||||
|
||||
const update = () => {
|
||||
const from = getRandomColor()
|
||||
// Calculate cojugate color based on the golden ratio
|
||||
const to: Color = [Math.floor(from[0] + (255 * GoldenRatio * 2)) % 255, from[1], from[2]]
|
||||
|
||||
setStart(from)
|
||||
setEnd(to)
|
||||
setDirection(Rand(0, 360))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
update()
|
||||
const interval = setInterval(update, Duration)
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
||||
return <div className={'animated-background'} style={{
|
||||
backgroundImage: valuesToGradient(direction, start, end),
|
||||
}} />
|
||||
}
|
||||
|
||||
export default AnimatedBackground
|
25
components/Cursor.tsx
Normal file
25
components/Cursor.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react'
|
||||
|
||||
import { useIsMousePresent, useMousePosition } from '../utils/hooks'
|
||||
|
||||
|
||||
|
||||
const Cursor: React.FC = () => {
|
||||
const mouse = useMousePosition()
|
||||
const present = useIsMousePresent()
|
||||
|
||||
return present
|
||||
? <span style={{
|
||||
position: 'fixed',
|
||||
top: mouse.absolute.y,
|
||||
left: mouse.absolute.x,
|
||||
width: '1em',
|
||||
height: '1em',
|
||||
borderRadius: '1em',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
backgroundColor: '#000000',
|
||||
}} />
|
||||
: null
|
||||
}
|
||||
|
||||
export default Cursor
|
46
components/LetterAnimation.tsx
Normal file
46
components/LetterAnimation.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import anime from 'animejs'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
|
||||
import { Duration } from '../utils/config'
|
||||
|
||||
|
||||
|
||||
export type LettersProps = {
|
||||
text: string
|
||||
delay?: number
|
||||
}
|
||||
|
||||
const LetterAnimation: React.FC<LettersProps> = React.memo(({ text, delay }) => {
|
||||
|
||||
const letters = useRef<HTMLElement>(null)
|
||||
|
||||
const animate = () => {
|
||||
if (!letters || !letters.current) return
|
||||
|
||||
const wrapper = letters.current
|
||||
wrapper.innerHTML = wrapper.innerText.replace(
|
||||
/./g,
|
||||
l => `<span class='letter'>${l}</span>`,
|
||||
)
|
||||
|
||||
anime({
|
||||
targets: wrapper.querySelectorAll(`.letter`),
|
||||
translateX: [40, 0],
|
||||
rotateY: [-20, 0],
|
||||
opacity: [0, 1],
|
||||
// color: () => getRandomColor(),
|
||||
easing: 'easeOutExpo',
|
||||
duration: Duration / 3,
|
||||
delay: (el, i) => (delay || 0) + 250 + 25 * i,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
useEffect(animate)
|
||||
|
||||
return <span ref={letters} className="letters">
|
||||
{text}
|
||||
</span>
|
||||
})
|
||||
|
||||
export default LetterAnimation
|
34
components/Parallax.tsx
Normal file
34
components/Parallax.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import React from 'react'
|
||||
|
||||
import { useMousePosition, useOrientation } from '../utils/hooks'
|
||||
|
||||
|
||||
|
||||
type RenderProps = {
|
||||
x: string,
|
||||
y: string
|
||||
}
|
||||
|
||||
const Render: React.FC<RenderProps> = React.memo(({ children, x, y }) => <div style={{
|
||||
transform: `rotateX(${y}) rotateY(${x})`,
|
||||
transition: `transform .1s`,
|
||||
}}>
|
||||
{children}
|
||||
</div>)
|
||||
|
||||
const Parallax: React.FC = ({ children }) => {
|
||||
|
||||
const orientation = useOrientation(true)
|
||||
const mouse = useMousePosition()
|
||||
const convertToDeg = (current: number, factor: number) => `${((.5 - current) * factor).toFixed(2)}deg`
|
||||
|
||||
const orientationFactor = 3
|
||||
const x = orientation ? Math.min(orientation.x / orientationFactor, 1) : mouse.relative.x
|
||||
const y = orientation ? Math.min(orientation.y / orientationFactor, 1) : mouse.relative.y
|
||||
|
||||
return <Render y={convertToDeg(y, 2)} x={convertToDeg(x, .75)}>
|
||||
{children}
|
||||
</Render>
|
||||
}
|
||||
|
||||
export default Parallax
|
8
components/Suspend.tsx
Normal file
8
components/Suspend.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import React, { Suspense } from 'react'
|
||||
|
||||
|
||||
const Suspend: (C: React.ComponentType) => React.ComponentType = (C) => () => {
|
||||
return <Suspense fallback={<span>...</span>} children={<C/>}/>
|
||||
}
|
||||
|
||||
export default Suspend
|
15
components/staticText.tsx
Normal file
15
components/staticText.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react'
|
||||
|
||||
import '../styles/static.styl'
|
||||
|
||||
|
||||
|
||||
const StaticText: React.FC = ({ children }) => {
|
||||
return <div className={'static'}>
|
||||
<div className={'content'}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
export default StaticText
|
Reference in New Issue
Block a user