mirror of
https://github.com/cupcakearmy/fantus.git
synced 2024-12-22 16:26:25 +00:00
components
This commit is contained in:
parent
e1e4c06d08
commit
94ac7b29aa
162
components/background.tsx
Normal file
162
components/background.tsx
Normal file
@ -0,0 +1,162 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { PerspectiveCamera, Scene, BufferGeometry, BufferAttribute, ShaderMaterial, Color, Points, WebGLRenderer, Camera } from 'three'
|
||||
|
||||
import '../styles/backgorund.styl'
|
||||
|
||||
// const SEPARATION = 150, AMOUNTX = 200, AMOUNTY = 200, HEIGHT = 75
|
||||
const SEPARATION = 150, AMOUNTX = 50, AMOUNTY = 50, HEIGHT = 75
|
||||
|
||||
let container: HTMLElement | null
|
||||
let camera: PerspectiveCamera
|
||||
let scene: Scene
|
||||
let renderer: WebGLRenderer
|
||||
|
||||
let count = 1
|
||||
let particles: Points
|
||||
|
||||
let mouseX = 0
|
||||
let mouseY = 0
|
||||
let windowHalfX = window.innerWidth / 2
|
||||
let windowHalfY = window.innerHeight / 2
|
||||
|
||||
function init() {
|
||||
container = window.document.getElementById('bg') || document.createElement('div')
|
||||
|
||||
document.body.appendChild(container)
|
||||
camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000000)
|
||||
scene = new Scene()
|
||||
|
||||
const numParticles = AMOUNTX * AMOUNTY
|
||||
const positions = new Float32Array(numParticles * 3)
|
||||
const scales = new Float32Array(numParticles)
|
||||
|
||||
let i = 0, j = 0
|
||||
for (let ix = 0; ix < AMOUNTX; ix++) {
|
||||
for (let iy = 0; iy < AMOUNTY; iy++) {
|
||||
positions[i] = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2) // x
|
||||
positions[i + 1] = 0 // y
|
||||
positions[i + 2] = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2) // z
|
||||
scales[j] = 1
|
||||
i += 3
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
const geometry = new BufferGeometry()
|
||||
geometry.setAttribute('position', new BufferAttribute(positions, 3))
|
||||
geometry.setAttribute('scale', new BufferAttribute(scales, 1))
|
||||
|
||||
const material = new ShaderMaterial({
|
||||
uniforms: {
|
||||
color: { value: new Color(0xffffff) },
|
||||
},
|
||||
vertexShader: document.getElementById('vertexshader')?.textContent || '',
|
||||
fragmentShader: document.getElementById('fragmentshader')?.textContent || ''
|
||||
})
|
||||
|
||||
particles = new Points(geometry, material)
|
||||
scene.add(particles)
|
||||
|
||||
renderer = new WebGLRenderer({ antialias: true })
|
||||
renderer.setPixelRatio(window.devicePixelRatio)
|
||||
renderer.setSize(window.innerWidth, window.innerHeight)
|
||||
|
||||
container.appendChild(renderer.domElement)
|
||||
document.addEventListener('mousemove', onDocumentMouseMove, false)
|
||||
document.addEventListener('touchstart', onDocumentTouchStart, false)
|
||||
document.addEventListener('touchmove', onDocumentTouchMove, false)
|
||||
|
||||
window.addEventListener('resize', onWindowResize, false)
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
windowHalfX = window.innerWidth / 2
|
||||
windowHalfY = window.innerHeight / 2
|
||||
camera.aspect = window.innerWidth / window.innerHeight
|
||||
camera.updateProjectionMatrix()
|
||||
renderer.setSize(window.innerWidth, window.innerHeight)
|
||||
}
|
||||
|
||||
function setMouse(x: number, y: number) {
|
||||
mouseX = (x - windowHalfX) / windowHalfX
|
||||
mouseY = -(y - windowHalfY) / windowHalfY
|
||||
}
|
||||
|
||||
|
||||
function onDocumentMouseMove(event: MouseEvent) {
|
||||
setMouse(event.clientX, event.clientY)
|
||||
}
|
||||
|
||||
function onDocumentTouchStart(event: TouchEvent) {
|
||||
if (event.touches.length === 1) {
|
||||
event.preventDefault()
|
||||
setMouse(event.touches[0].pageX, event.touches[0].pageY)
|
||||
}
|
||||
}
|
||||
|
||||
function onDocumentTouchMove(event: TouchEvent) {
|
||||
if (event.touches.length === 1) {
|
||||
event.preventDefault()
|
||||
setMouse(event.touches[0].pageX, event.touches[0].pageY)
|
||||
}
|
||||
}
|
||||
|
||||
function animate() {
|
||||
requestAnimationFrame(animate)
|
||||
render()
|
||||
}
|
||||
|
||||
function render() {
|
||||
// Noence from 0.0 to 1.0
|
||||
const noence = (Math.sin(count / 4) + 1) / 2
|
||||
const noence_inv = 1 - noence
|
||||
|
||||
camera.position.x = -mouseX * 500
|
||||
camera.position.y = 1000 - mouseY * 500
|
||||
camera.position.z = 1000 - mouseY * 250
|
||||
camera.lookAt(scene.position)
|
||||
|
||||
if (particles.geometry instanceof BufferGeometry) {
|
||||
const positions = particles.geometry.attributes.position.array
|
||||
const scales = particles.geometry.attributes.scale.array
|
||||
let i = 0, j = 0
|
||||
for (let ix = 0; ix < AMOUNTX; ix++) {
|
||||
for (let iy = 0; iy < AMOUNTY; iy++) {
|
||||
const dx = Math.sin((ix + count) * 0.3)
|
||||
const dy = Math.sin((iy + count) * 0.5)
|
||||
// @ts-ignore
|
||||
positions[i + 1] = (dx * HEIGHT) + (dy * HEIGHT)
|
||||
// @ts-ignore
|
||||
scales[j] = (dx + 1) * 8 + (dy + 1) * 8
|
||||
i += 3
|
||||
j++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @ts-ignore
|
||||
particles.material.uniforms.color.value.setRGB(1 - 0.5 * noence_inv, 0.2 + 0.8 * noence, 1)
|
||||
if (particles.geometry.attributes.position instanceof BufferAttribute)
|
||||
particles.geometry.attributes.position.needsUpdate = true
|
||||
if (particles.geometry.attributes.scale instanceof BufferAttribute)
|
||||
particles.geometry.attributes.scale.needsUpdate = true
|
||||
|
||||
}
|
||||
renderer.render(scene, camera)
|
||||
|
||||
count += 0.05 + (0.01 * noence)
|
||||
}
|
||||
|
||||
const Background: React.FC = ({ children }) => {
|
||||
|
||||
useEffect(() => {
|
||||
init()
|
||||
animate()
|
||||
}, [])
|
||||
|
||||
return <div id='bg'>
|
||||
{children}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default Background
|
13
components/content.tsx
Normal file
13
components/content.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from 'react'
|
||||
|
||||
import '../styles/content.styl'
|
||||
|
||||
const Content: React.FC = ({ children }) => {
|
||||
return <div className='container'>
|
||||
{/* <div className='content'> */}
|
||||
{children}
|
||||
{/* </div> */}
|
||||
</div>
|
||||
}
|
||||
|
||||
export default Content
|
20
components/link.tsx
Normal file
20
components/link.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import React from 'react'
|
||||
import NextLink, { LinkProps } from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const Link: React.FC<LinkProps> = ({ href, children }) => {
|
||||
const router = useRouter()
|
||||
|
||||
let className = ''
|
||||
try {
|
||||
// @ts-ignore
|
||||
className = children.props.className || ''
|
||||
} catch { }
|
||||
|
||||
if (router.pathname === href)
|
||||
className = `${className} active`.trim()
|
||||
|
||||
return <NextLink href={href}>{React.cloneElement(children as React.ReactElement, { className })}</NextLink>
|
||||
}
|
||||
|
||||
export default Link
|
Loading…
Reference in New Issue
Block a user