mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-15 08:41:37 +00:00
feat(3d): add camera animation
This commit is contained in:
@ -50,6 +50,7 @@ const BocchiRubbishBin = (props: JSX.IntrinsicElements['group']) => {
|
|||||||
dispose={null}
|
dispose={null}
|
||||||
position={position}
|
position={position}
|
||||||
rotation={[Math.PI / 10, Math.PI / 10, 0]}
|
rotation={[Math.PI / 10, Math.PI / 10, 0]}
|
||||||
|
scale={0.7}
|
||||||
>
|
>
|
||||||
<mesh
|
<mesh
|
||||||
castShadow
|
castShadow
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { PerspectiveCamera } from '@react-three/drei/core/PerspectiveCamera';
|
||||||
import { Canvas } from '@react-three/fiber';
|
import { Canvas } from '@react-three/fiber';
|
||||||
import { lazy, Suspense, useMemo } from 'react';
|
import { lazy, Suspense, useMemo } from 'react';
|
||||||
import Loading from './loading';
|
|
||||||
import { PerspectiveCamera } from '@react-three/drei/core/PerspectiveCamera';
|
|
||||||
import { useMediaQuery } from 'react-responsive';
|
import { useMediaQuery } from 'react-responsive';
|
||||||
import { useTexture } from '@react-three/drei';
|
import Loading from './loading';
|
||||||
|
|
||||||
|
const DeskCamera = lazy(() => import('components/models/home/desk-camera'));
|
||||||
const ComputerModel = lazy(
|
const ComputerModel = lazy(
|
||||||
() => import('components/models/home/computer-model'),
|
() => import('components/models/home/computer-model'),
|
||||||
);
|
);
|
||||||
@ -29,14 +29,16 @@ const ComputerDesk = () => {
|
|||||||
<Suspense fallback={<Loading />}>
|
<Suspense fallback={<Loading />}>
|
||||||
<ambientLight intensity={1} />
|
<ambientLight intensity={1} />
|
||||||
<directionalLight position={[10, 10, 10]} intensity={0.5} />
|
<directionalLight position={[10, 10, 10]} intensity={0.5} />
|
||||||
<ComputerModel
|
<DeskCamera>
|
||||||
scale={scale}
|
<ComputerModel
|
||||||
position={[0.6, -7.2, 0]}
|
scale={scale}
|
||||||
rotation={[0, -Math.PI, 0]}
|
position={[0.6, -7.2, 0]}
|
||||||
/>
|
rotation={[0, -Math.PI, 0]}
|
||||||
|
/>
|
||||||
|
</DeskCamera>
|
||||||
<Target />
|
<Target />
|
||||||
<ReactLogo />
|
<ReactLogo />
|
||||||
<PerspectiveCamera makeDefault position={[0, 0, 30]} />
|
<PerspectiveCamera makeDefault position={[0, 0, 36]} />
|
||||||
<Bocchi />
|
<Bocchi />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
@ -61,6 +61,7 @@ export function Model(props: JSX.IntrinsicElements['group']) {
|
|||||||
|
|
||||||
const moniterTexture = useTexture('/texture/desk/monitor.png');
|
const moniterTexture = useTexture('/texture/desk/monitor.png');
|
||||||
const screenTexture = useTexture('/texture/desk/screen.png');
|
const screenTexture = useTexture('/texture/desk/screen.png');
|
||||||
|
const tableTexture = useTexture('/texture/desk/table.png');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group {...props} dispose={null}>
|
<group {...props} dispose={null}>
|
||||||
@ -107,13 +108,17 @@ export function Model(props: JSX.IntrinsicElements['group']) {
|
|||||||
receiveShadow
|
receiveShadow
|
||||||
geometry={nodes.Tv_tv_mat_0.geometry}
|
geometry={nodes.Tv_tv_mat_0.geometry}
|
||||||
material={materials.tv_mat}
|
material={materials.tv_mat}
|
||||||
/>
|
>
|
||||||
|
<meshMatcapMaterial map={moniterTexture} />
|
||||||
|
</mesh>
|
||||||
<mesh
|
<mesh
|
||||||
castShadow
|
castShadow
|
||||||
receiveShadow
|
receiveShadow
|
||||||
geometry={nodes.table_table_mat_0.geometry}
|
geometry={nodes.table_table_mat_0.geometry}
|
||||||
material={materials.table_mat}
|
material={materials.table_mat}
|
||||||
/>
|
>
|
||||||
|
<meshMatcapMaterial map={tableTexture} />
|
||||||
|
</mesh>
|
||||||
<mesh
|
<mesh
|
||||||
castShadow
|
castShadow
|
||||||
receiveShadow
|
receiveShadow
|
||||||
|
43
components/models/home/desk-camera.tsx
Normal file
43
components/models/home/desk-camera.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import { JSX, useRef } from 'react';
|
||||||
|
import { useFrame } from '@react-three/fiber';
|
||||||
|
import { easing } from 'maath';
|
||||||
|
import { useMediaQuery } from 'react-responsive';
|
||||||
|
|
||||||
|
const DeskCamera = ({ children }: { children: JSX.Element }) => {
|
||||||
|
const groupRef = useRef<THREE.Group>(null);
|
||||||
|
|
||||||
|
const isMobile = useMediaQuery({ query: '(max-width: 768px)' });
|
||||||
|
useFrame((state, delta) => {
|
||||||
|
easing.damp3(state.camera.position, [0, 0, 26], 0.25, delta);
|
||||||
|
|
||||||
|
if (!isMobile && groupRef.current) {
|
||||||
|
const x = (() => {
|
||||||
|
const _x = state.pointer.y / 3;
|
||||||
|
if (_x < 0) {
|
||||||
|
if (_x <= -0.14) {
|
||||||
|
return -0.14;
|
||||||
|
} else {
|
||||||
|
return _x;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_x >= 0.14) {
|
||||||
|
return 0.14;
|
||||||
|
} else {
|
||||||
|
return _x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
easing.dampE(
|
||||||
|
groupRef.current.rotation,
|
||||||
|
[-x, -state.pointer.x / 5, 0],
|
||||||
|
0.25,
|
||||||
|
delta,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return <group ref={groupRef}>{children}</group>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeskCamera;
|
@ -32,6 +32,7 @@
|
|||||||
"algoliasearch": "^5.25.0",
|
"algoliasearch": "^5.25.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"gsap": "^3.13.0",
|
"gsap": "^3.13.0",
|
||||||
|
"maath": "^0.10.8",
|
||||||
"next": "15.3.2",
|
"next": "15.3.2",
|
||||||
"next-mdx-remote": "^5.0.0",
|
"next-mdx-remote": "^5.0.0",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
|
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -59,6 +59,9 @@ importers:
|
|||||||
gsap:
|
gsap:
|
||||||
specifier: ^3.13.0
|
specifier: ^3.13.0
|
||||||
version: 3.13.0
|
version: 3.13.0
|
||||||
|
maath:
|
||||||
|
specifier: ^0.10.8
|
||||||
|
version: 0.10.8(@types/three@0.176.0)(three@0.176.0)
|
||||||
next:
|
next:
|
||||||
specifier: 15.3.2
|
specifier: 15.3.2
|
||||||
version: 15.3.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.0)
|
version: 15.3.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.89.0)
|
||||||
|
Reference in New Issue
Block a user