Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audrey new #175

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 97 additions & 72 deletions app/page.jsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,107 @@
'use client'

import dynamic from 'next/dynamic'
import { Suspense } from 'react'

const Logo = dynamic(() => import('@/components/canvas/Examples').then((mod) => mod.Logo), { ssr: false })
const Dog = dynamic(() => import('@/components/canvas/Examples').then((mod) => mod.Dog), { ssr: false })
const Duck = dynamic(() => import('@/components/canvas/Examples').then((mod) => mod.Duck), { ssr: false })
const View = dynamic(() => import('@/components/canvas/View').then((mod) => mod.View), {
ssr: false,
loading: () => (
<div className='flex h-96 w-full flex-col items-center justify-center'>
<svg className='-ml-1 mr-3 h-5 w-5 animate-spin text-black' fill='none' viewBox='0 0 24 24'>
<circle className='opacity-25' cx='12' cy='12' r='10' stroke='currentColor' strokeWidth='4' />
<path
className='opacity-75'
fill='currentColor'
d='M4 12a8 8 0 0 1 8-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 0 1 4 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'
/>
</svg>
</div>
),
})
const Common = dynamic(() => import('@/components/canvas/View').then((mod) => mod.Common), { ssr: false })
import { useState, useEffect } from 'react'
import Image from 'next/image'
import styles from './page.module.css'

export default function Page() {
return (
<>
<div className='mx-auto flex w-full flex-col flex-wrap items-center md:flex-row lg:w-4/5'>
{/* jumbo */}
<div className='flex w-full flex-col items-start justify-center p-12 text-center md:w-2/5 md:text-left'>
<p className='w-full uppercase'>Next + React Three Fiber</p>
<h1 className='my-4 text-5xl font-bold leading-tight'>Next 3D Starter</h1>
<p className='mb-8 text-2xl leading-normal'>A minimalist starter for React, React-three-fiber and Threejs.</p>
</div>
const [answer, setAnswer] = useState(null)

<div className='w-full text-center md:w-3/5'>
<View className='flex h-96 w-full flex-col items-center justify-center'>
<Suspense fallback={null}>
<Logo route='/blob' scale={0.6} position={[0, 0, 0]} />
<Common />
</Suspense>
</View>
</div>
</div>
useEffect(() => {
const playSound = async () => {
try {
const audio = new Audio('https://www.myinstants.com/media/sounds/minecraft-oof.mp3')
audio.volume = 0.7
await audio.play()
} catch (error) {
console.log("Audio playback failed:", error)
}
}

playSound()
}, [])

<div className='mx-auto flex w-full flex-col flex-wrap items-center p-12 md:flex-row lg:w-4/5'>
{/* first row */}
<div className='relative h-48 w-full py-6 sm:w-1/2 md:my-12 md:mb-40'>
<h2 className='mb-3 text-3xl font-bold leading-none text-gray-800'>Events are propagated</h2>
<p className='mb-8 text-gray-600'>Drag, scroll, pinch, and rotate the canvas to explore the 3D scene.</p>
</div>
<div className='relative my-12 h-48 w-full py-6 sm:w-1/2 md:mb-40'>
<View orbit className='relative h-full sm:h-48 sm:w-full'>
<Suspense fallback={null}>
<Dog scale={2} position={[0, -1.6, 0]} rotation={[0.0, -0.3, 0]} />
<Common color={'lightpink'} />
</Suspense>
</View>
</div>
{/* second row */}
<div className='relative my-12 h-48 w-full py-6 sm:w-1/2 md:mb-40'>
<View orbit className='relative h-full animate-bounce sm:h-48 sm:w-full'>
<Suspense fallback={null}>
<Duck route='/blob' scale={2} position={[0, -1.6, 0]} />
<Common color={'lightblue'} />
</Suspense>
</View>
const handleYesClick = async () => {
try {
const audio = new Audio('https://www.myinstants.com/media/sounds/anime-wow-sound-effect.mp3')
audio.volume = 0.7
await audio.play()
} catch (error) {
console.log("Audio playback failed:", error)
}
setAnswer(true)
}

const handleNoClick = async () => {
try {
const audio = new Audio('https://www.myinstants.com/media/sounds/emotional-damage-meme.mp3')
audio.volume = 0.7
await audio.play()
} catch (error) {
console.log("Audio playback failed:", error)
}
setAnswer(false)
}

return (
<div className='min-h-screen bg-pink-50'>
{answer === null ? (
<div className='flex min-h-screen flex-col items-center justify-center'>
<div className='mb-12 text-center'>
<h1 className='mb-8 text-center text-5xl font-bold text-pink-600'>will you be my valentine?</h1>

<div className='flex justify-center gap-8'>
<button
onClick={handleYesClick}
className='rounded-lg bg-pink-500 px-8 py-3 text-xl font-bold text-white transition-colors hover:bg-pink-600'
>
yes! uwu
</button>
<button
onClick={handleNoClick}
className='rounded-lg bg-gray-500 px-8 py-3 text-xl font-bold text-white transition-colors hover:bg-gray-600'
>
naur
</button>
</div>
</div>
</div>
<div className='w-full p-6 sm:w-1/2'>
<h2 className='mb-3 text-3xl font-bold leading-none text-gray-800'>Dom and 3D are synchronized</h2>
<p className='mb-8 text-gray-600'>
3D Divs are renderer through the View component. It uses gl.scissor to cut the viewport into segments. You
tie a view to a tracking div which then controls the position and bounds of the viewport. This allows you to
have multiple views with a single, performant canvas. These views will follow their tracking elements,
scroll along, resize, etc.
</p>
) : (
<div className='flex min-h-screen flex-col items-center justify-center gap-8'>
<h1 className='text-4xl font-bold text-pink-600'>
{answer ? "yay #jesh moots ship sail " : "was crack ship anyways (click go back)"}
</h1>
{answer ? (
<div className={`relative size-96 ${styles.danceContainer}`}>
<Image
src="/img/scores/chan.png"
alt="Happy Chan"
fill
sizes="(max-width: 768px) 100vw, 384px"
className={`object-contain ${styles.dance}`}
priority
/>
</div>
) : (
<div className='relative size-96'>
<Image
src="/img/scores/lottie.png"
alt="Sad Lottie"
fill
sizes="(max-width: 768px) 100vw, 384px"
className={`object-contain ${styles.sad}`}
priority
/>
</div>
)}
<button
onClick={() => setAnswer(null)}
className='rounded-lg bg-pink-500 px-6 py-2 text-lg font-bold text-white transition-colors hover:bg-pink-600'
>
Go Back
</button>
</div>
</div>
</>
)}
</div>
)
}
46 changes: 46 additions & 0 deletions app/page.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@keyframes rainbow {
0% { background-color: #ff0000; }
17% { background-color: #ff00ff; }
33% { background-color: #0000ff; }
50% { background-color: #00ffff; }
67% { background-color: #00ff00; }
83% { background-color: #ffff00; }
100% { background-color: #ff0000; }
}

@keyframes dance {
0% { transform: translateY(0) rotate(0deg); }
25% { transform: translateY(-20px) rotate(10deg); }
50% { transform: translateY(0) rotate(0deg); }
75% { transform: translateY(-20px) rotate(-10deg); }
100% { transform: translateY(0) rotate(0deg); }
}

@keyframes sad {
0% {
transform: translateY(0);
opacity: 1;
filter: grayscale(0);
}
100% {
transform: translateY(50px);
opacity: 0.5;
filter: grayscale(1);
}
}

.danceContainer {
padding: 20px;
border-radius: 20px;
animation: rainbow 3s linear infinite;
}

.dance {
animation: dance 0.5s ease-in-out infinite;
transform-origin: bottom center;
}

.sad {
animation: sad 2s ease-in forwards;
transform-origin: center;
}
24 changes: 24 additions & 0 deletions components/canvas/Examples.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as THREE from 'three'
import { useEffect, useRef } from 'react'

export function Chan({ scale = 1, position = [0, 0, 0], rotation = [0, 0, 0] }) {
const meshRef = useRef()

useEffect(() => {
const texture = new THREE.TextureLoader().load('/chan.png')
texture.minFilter = THREE.LinearFilter
texture.magFilter = THREE.LinearFilter

if (meshRef.current) {
meshRef.current.material.map = texture
meshRef.current.material.needsUpdate = true
}
}, [])

return (
<mesh ref={meshRef} position={position} rotation={rotation} scale={scale}>
<planeGeometry args={[1, 1]} />
<meshBasicMaterial transparent side={THREE.DoubleSide} />
</mesh>
)
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -18,13 +18,13 @@
},
"dependencies": {
"@ducanh2912/next-pwa": "^10.0.0",
"@react-three/drei": "^9.92.7",
"@react-three/fiber": "^8.15.12",
"@react-three/drei": "^9.121.5",
"@react-three/fiber": "^8.17.14",
"glsl-random": "^0.0.5",
"next": "^14.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"three": "^0.160.0",
"three": "^0.160.1",
"three-stdlib": "^2.28.9",
"tunnel-rat": "^0.1.2"
},
1 change: 1 addition & 0 deletions public/audio/dramatic.mp3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Binary file added public/cat.glb
Binary file not shown.
1 change: 1 addition & 0 deletions public/chan.glb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Binary GLB file content would go here - you'll need to provide your own chan.glb model file]
Binary file added public/img/scores/chan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/scores/lottie.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Oops, something went wrong.