This commit is contained in:
Mackie 2026-06-07 08:19:42 +08:00
parent da0d7ba0d2
commit f09bc39a12
11 changed files with 92 additions and 85 deletions

View file

@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "ByMackie 3D Animation",
description: "showcase bymackie",
};
export default function RootLayout({

View file

@ -1,64 +1,17 @@
import Image from "next/image";
'use client';
import dynamic from 'next/dynamic';
const ShowcaseCanvas = dynamic(
() => import('@/components/three/ShowcaseCanvas'),
{ ssr: false }
);
export default function Home() {
return (
<div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
<main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={100}
height={20}
priority
/>
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
To get started, edit the page.tsx file.
</h1>
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
Looking for a starting point or more instructions? Head over to{" "}
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Templates
</a>{" "}
or the{" "}
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
Learning
</a>{" "}
center.
</p>
</div>
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
<a
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
Deploy Now
</a>
<a
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
</div>
<div className="flex flex-col items-center justify-center min-h-screen bg-zinc-50 dark:bg-black p-8">
<main className="w-full max-w-3xl flex flex-col gap-8">
<ShowcaseCanvas />
<h1 className="text-3xl font-semibold text-black dark:text-zinc-50">3D Showcase</h1>
</main>
</div>
);

View file

@ -1,5 +1,4 @@
'use client';
import { useGLTF } from '@react-three/drei';
export function Model({ url }: { url: string }) {

View file

@ -1,36 +1,51 @@
'use client';
import { Canvas } from '@react-three/fiber';
import { OrbitControls, Stage } from '@react-three/drei';
import { OrbitControls, Stage, ContactShadows, Environment } from '@react-three/drei';
import { Suspense } from 'react';
import { EffectComposer, Bloom, Noise, Vignette } from '@react-three/postprocessing';
import { useAssetLoader } from '@/hooks/useAssetLoader';
import { Model } from './Model';
import { motion } from 'framer-motion';
export default function ShowcaseCanvas() {
const { asset, loading, error } = useAssetLoader('/assets.json');
if (loading || error) return null;
return (
<div className="h-[500px] w-full border border-zinc-800 rounded-xl overflow-hidden bg-black">
<Canvas dpr={[1, 2]} shadows camera={{ fov: 45 }}>
<color attach="background" args={['#050505']} />
// Added 'bg-zinc-50' and a subtle 'bg-grid' style pattern
// Replace your div className with this:
<div className="relative h-[650px] w-full rounded-2xl overflow-hidden shadow-2xl bg-stone-100 border border-stone-200 bg-[linear-gradient(to_right,#d6d3d1_1px,transparent_1px),linear-gradient(to_bottom,#d6d3d1_1px,transparent_1px)] bg-[size:40px_40px]">
{/* 3D Canvas */}
<Canvas shadows camera={{ position: [0, 0, 4], fov: 45 }}>
<Suspense fallback={null}>
<Stage intensity={0.5} environment="city">
{asset && <Model url={asset.modelUrl} />}
<Environment preset="city" />
<Stage intensity={0.5} adjustCamera={false}>
<Model url="/models/shoe.glb" />
</Stage>
<ContactShadows opacity={0.4} scale={10} blur={2} far={4.5} />
</Suspense>
<EffectComposer disableNormalPass>
<Bloom luminanceThreshold={1} mipmapBlur intensity={1.5} />
<Noise opacity={0.05} />
<Vignette eskil={false} offset={0.1} darkness={1.1} />
</EffectComposer>
<OrbitControls makeDefault />
<OrbitControls
makeDefault
enablePan={false}
minPolarAngle={Math.PI / 4}
maxPolarAngle={Math.PI / 1.75}
/>
</Canvas>
{/* UI Overlay */}
<motion.div
initial={{ opacity: 0, x: 50 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.8, ease: "easeOut" }}
className="absolute top-10 right-10 z-10 w-72 bg-black/80 backdrop-blur-xl p-6 rounded-2xl text-white shadow-2xl"
>
<h2 className="text-2xl font-bold tracking-tight">AIR JORDAN 1</h2>
<p className="text-zinc-300 mt-2 text-sm leading-relaxed">
Engineered for performance and style. Experience the pinnacle of sneaker culture.
</p>
<div className="flex items-center justify-between mt-6">
<span className="text-lg font-bold">$170.00</span>
<button className="bg-white text-black px-5 py-2 text-sm rounded-full font-bold hover:bg-zinc-200 transition-colors duration-300">
BUY NOW
</button>
</div>
</motion.div>
</div>
);
}

View file

@ -1,7 +1,8 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
// Add this to allow network access
allowedDevOrigins: ['192.168.50.47'],
};
export default nextConfig;

View file

@ -13,6 +13,7 @@
"@react-three/fiber": "^9.6.1",
"@react-three/postprocessing": "^3.0.4",
"@types/three": "^0.184.1",
"framer-motion": "^12.40.0",
"next": "16.2.7",
"react": "19.2.4",
"react-dom": "19.2.4",

38
pnpm-lock.yaml generated
View file

@ -20,6 +20,9 @@ importers:
'@types/three':
specifier: ^0.184.1
version: 0.184.1
framer-motion:
specifier: ^12.40.0
version: 12.40.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
next:
specifier: 16.2.7
version: 16.2.7(@babel/core@7.29.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
@ -1290,6 +1293,20 @@ packages:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
framer-motion@12.40.0:
resolution: {integrity: sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg==}
peerDependencies:
'@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
peerDependenciesMeta:
'@emotion/is-prop-valid':
optional: true
react:
optional: true
react-dom:
optional: true
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@ -1724,6 +1741,12 @@ packages:
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
motion-dom@12.40.0:
resolution: {integrity: sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg==}
motion-utils@12.39.0:
resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -3609,6 +3632,15 @@ snapshots:
dependencies:
is-callable: 1.2.7
framer-motion@12.40.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
dependencies:
motion-dom: 12.40.0
motion-utils: 12.39.0
tslib: 2.8.1
optionalDependencies:
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
function-bind@1.1.2: {}
function.prototype.name@1.1.8:
@ -4012,6 +4044,12 @@ snapshots:
minimist@1.2.8: {}
motion-dom@12.40.0:
dependencies:
motion-utils: 12.39.0
motion-utils@12.39.0: {}
ms@2.1.3: {}
n8ao@1.10.1(postprocessing@6.39.1(three@0.184.0))(three@0.184.0):

BIN
public/models/shoe_blue.glb Normal file

Binary file not shown.

BIN
public/models/shoe_grey.glb Normal file

Binary file not shown.

BIN
public/models/shoe_red.glb Normal file

Binary file not shown.