mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-16 01:01:38 +00:00
update mouse hover
add animation
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
* @type {import('next').NextConfig}
|
* @type {import('next').NextConfig}
|
||||||
*/
|
*/
|
||||||
const isExport = process.env.NEXT_BUILD === 'export';
|
const isExport = process.env.NEXT_BUILD === 'export';
|
||||||
|
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
/* config options here */
|
/* config options here */
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
@ -10,10 +11,9 @@ const nextConfig = {
|
|||||||
images: isExport ? { unoptimized: true } : {},
|
images: isExport ? { unoptimized: true } : {},
|
||||||
experimental: {
|
experimental: {
|
||||||
// runtime: 'nodejs',
|
// runtime: 'nodejs',
|
||||||
// outputStandalone: true,
|
|
||||||
},
|
},
|
||||||
compiler: {
|
compiler: {
|
||||||
removeConsole: true,
|
removeConsole: process.env.NODE_ENV === 'production',
|
||||||
},
|
},
|
||||||
// assetPrefix: isExport ? './' : undefined,
|
// assetPrefix: isExport ? './' : undefined,
|
||||||
// images:
|
// images:
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
"rehype-slug": "^5.0.1",
|
"rehype-slug": "^5.0.1",
|
||||||
"remark-frontmatter": "^4.0.1",
|
"remark-frontmatter": "^4.0.1",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"rua-three": "^1.0.9",
|
"rua-three": "^1.1.1",
|
||||||
"sharp": "^0.31.0",
|
"sharp": "^0.31.0",
|
||||||
"stats.js": "^0.17.0",
|
"stats.js": "^0.17.0",
|
||||||
"three": "^0.145.0"
|
"three": "^0.145.0"
|
||||||
|
@ -2,7 +2,7 @@ import cn from 'classnames';
|
|||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import Image from 'next/future/image';
|
import Image from 'next/future/image';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { InitFn, THREE, useThree } from 'rua-three';
|
import { InitFn, THREE, useThree } from 'rua-three';
|
||||||
import styles from 'styles/index/index.module.css';
|
import styles from 'styles/index/index.module.css';
|
||||||
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||||
@ -14,6 +14,9 @@ const Loading = dynamic(() => import('components/RUA/loading/RUALoading'));
|
|||||||
const manager = new THREE.LoadingManager();
|
const manager = new THREE.LoadingManager();
|
||||||
const gltfLoader = new GLTFLoader(manager);
|
const gltfLoader = new GLTFLoader(manager);
|
||||||
|
|
||||||
|
const rotationY = 0.4;
|
||||||
|
const rotationX = 0.18;
|
||||||
|
|
||||||
const Home: NextPageWithLayout = () => {
|
const Home: NextPageWithLayout = () => {
|
||||||
const wrapper = useRef<HTMLDivElement>(null);
|
const wrapper = useRef<HTMLDivElement>(null);
|
||||||
const [size, setSize] = useState({
|
const [size, setSize] = useState({
|
||||||
@ -30,7 +33,7 @@ const Home: NextPageWithLayout = () => {
|
|||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setCanvasSize = () => {
|
const setCanvasSize = useCallback(() => {
|
||||||
if (!wrapper.current) return;
|
if (!wrapper.current) return;
|
||||||
const width = wrapper.current.clientWidth;
|
const width = wrapper.current.clientWidth;
|
||||||
const height = wrapper.current.clientHeight;
|
const height = wrapper.current.clientHeight;
|
||||||
@ -38,7 +41,7 @@ const Home: NextPageWithLayout = () => {
|
|||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
});
|
});
|
||||||
};
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCanvasSize();
|
setCanvasSize();
|
||||||
window.addEventListener('resize', setCanvasSize);
|
window.addEventListener('resize', setCanvasSize);
|
||||||
@ -46,46 +49,97 @@ const Home: NextPageWithLayout = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('resize', setCanvasSize);
|
window.removeEventListener('resize', setCanvasSize);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [setCanvasSize]);
|
||||||
|
|
||||||
const init: InitFn = ({ scene, camera, controls, frameArea }) => {
|
const init: InitFn = ({
|
||||||
controls.enablePan = false;
|
scene,
|
||||||
controls.minDistance = 1;
|
camera,
|
||||||
controls.minPolarAngle = Math.PI * 0.2;
|
controls,
|
||||||
controls.maxPolarAngle = Math.PI * 0.5;
|
frameArea,
|
||||||
controls.maxAzimuthAngle = Math.PI * 0.2;
|
isOrbitControls,
|
||||||
camera.position.set(0, 5, 5);
|
isPerspectiveCamera,
|
||||||
|
addWindowEvent,
|
||||||
|
addRenderCallback,
|
||||||
|
}) => {
|
||||||
|
if (isOrbitControls(controls)) {
|
||||||
|
controls.enableRotate = false;
|
||||||
|
controls.enablePan = false;
|
||||||
|
controls.enableZoom = false;
|
||||||
|
controls.minDistance = 1;
|
||||||
|
controls.minPolarAngle = Math.PI * 0.2;
|
||||||
|
controls.maxPolarAngle = Math.PI * 0.5;
|
||||||
|
controls.maxAzimuthAngle = Math.PI * 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
const light = new THREE.SpotLight(0xffffff, 1.4, 100, 15);
|
const light = new THREE.SpotLight(0xffffff, 2, 100, 15);
|
||||||
scene.add(new THREE.AmbientLight(0xffffff, 0.8));
|
scene.add(new THREE.AmbientLight(0xffffff, 1));
|
||||||
scene.add(light);
|
scene.add(light);
|
||||||
|
|
||||||
const handleLoad = (gltf: GLTF) => {
|
const handleLoad = (gltf: GLTF) => {
|
||||||
const root = gltf.scene;
|
const root = gltf.scene;
|
||||||
scene.add(root);
|
scene.add(root);
|
||||||
|
|
||||||
|
const clock = new THREE.Clock();
|
||||||
|
const mixer = new THREE.AnimationMixer(root);
|
||||||
|
gltf.animations.forEach((clip) => {
|
||||||
|
mixer.clipAction(clip).play();
|
||||||
|
});
|
||||||
|
addRenderCallback((time) => {
|
||||||
|
mixer.update(clock.getDelta());
|
||||||
|
});
|
||||||
|
|
||||||
const box = new THREE.Box3().setFromObject(root);
|
const box = new THREE.Box3().setFromObject(root);
|
||||||
|
|
||||||
const boxSize = box.getSize(new THREE.Vector3()).length();
|
const boxSize = box.getSize(new THREE.Vector3()).length();
|
||||||
const boxCenter = box.getCenter(new THREE.Vector3());
|
const boxCenter = box.getCenter(new THREE.Vector3());
|
||||||
|
|
||||||
light.target = root;
|
light.target = root;
|
||||||
light.position.set(0, 2, 4);
|
light.position.set(0, 2, 6);
|
||||||
light.rotateX(Math.PI * 0.4);
|
light.rotateX(Math.PI * 0.4);
|
||||||
frameArea(boxSize * 0.8, boxSize, boxCenter, camera);
|
isPerspectiveCamera(camera) &&
|
||||||
|
frameArea(boxSize * 0.8, boxSize, boxCenter, camera);
|
||||||
|
|
||||||
controls.maxDistance = boxSize * 10;
|
// controls.maxDistance = boxSize * 10;
|
||||||
controls.target.copy(boxCenter);
|
controls.target.copy(boxCenter);
|
||||||
controls.update();
|
controls.update();
|
||||||
|
|
||||||
|
const halfWidth = Math.floor(window.innerWidth / 2);
|
||||||
|
const halfHeight = Math.floor(window.innerHeight / 2);
|
||||||
|
|
||||||
|
const updateMousePosition = (e: MouseEvent | globalThis.TouchEvent) => {
|
||||||
|
let x;
|
||||||
|
let y;
|
||||||
|
if (e instanceof MouseEvent) {
|
||||||
|
x = e.clientX;
|
||||||
|
y = e.clientY;
|
||||||
|
} else {
|
||||||
|
x = e.touches[0].clientX;
|
||||||
|
y = e.touches[0].clientY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// > 0 is right, < 0 is left
|
||||||
|
const directionX = x - halfWidth;
|
||||||
|
const directionY = y - halfHeight;
|
||||||
|
|
||||||
|
// if (directionX > 0) root.rotation.y += 0.01;
|
||||||
|
root.rotation.y = rotationY * (directionX / halfWidth);
|
||||||
|
root.rotation.x = rotationX * (directionY / halfHeight);
|
||||||
|
};
|
||||||
|
|
||||||
|
addWindowEvent('mousemove', updateMousePosition, {
|
||||||
|
passive: true,
|
||||||
|
});
|
||||||
|
addWindowEvent('touchmove', updateMousePosition, {
|
||||||
|
passive: true,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
gltfLoader.load('/models/just_a_hungry_cat/scene.gltf', handleLoad);
|
gltfLoader.load('./models/just_a_hungry_cat/scene.gltf', handleLoad);
|
||||||
};
|
};
|
||||||
const { ref } = useThree({
|
const { ref } = useThree({
|
||||||
init,
|
init,
|
||||||
...size,
|
...size,
|
||||||
alpha: true,
|
alpha: true,
|
||||||
renderOnDemand: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -7761,10 +7761,10 @@ rimraf@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
rua-three@^1.0.9:
|
rua-three@^1.1.1:
|
||||||
version "1.0.9"
|
version "1.1.1"
|
||||||
resolved "https://registry.npmjs.org/rua-three/-/rua-three-1.0.9.tgz#64f6d9d27ff6982fabe82125cd9d5013725f6c51"
|
resolved "https://registry.npmjs.org/rua-three/-/rua-three-1.1.1.tgz#c6d2e28fc60ed4e3bde5018332787c014515d7a3"
|
||||||
integrity sha512-elvrI+NLCx0t50jJsxTVktqmUXEM7EmwbDC9b1Js4lupnjVIvkCFknZ+7AMGRIri5150XxTxr03aH30hiqFY8w==
|
integrity sha512-eESIlFHebKIQjWKlDGoRHmeXTniCu32o8U5DhKCYXtDXC9kyXcOa5mqJBAR7nRD1QCrSd7LFKg+wdkSIKdVIYQ==
|
||||||
|
|
||||||
run-async@^2.4.0:
|
run-async@^2.4.0:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
|
Reference in New Issue
Block a user