- vừa được xem lúc

Làm việc Modal 3D với Threejs trong reactjs bằng thư viện react-three-fiber

0 0 25

Người đăng: HuDu Pa

Theo Viblo Asia

Hiển thị một file .jbx (modal 3d) sử dụng thư viện Three.js trong ReactJS

Để hiển thị một file .jbx (modal 3d) sử dụng thư viện Three.js trong ReactJS, chúng ta có thể tạo một React component và sử dụng thư viện three.js để tạo ra một scene 3D để hiển thị modal.

Đầu tiên, cài đặt thư viện three.js và thư viện react-three-fiber bằng cách chạy lệnh sau trong terminal:

npm install three react-three-fiber

Sau đó, tạo một component React với tên là "ThreeJSModal" như sau:

import React, { useRef, useState } from "react";
import { useLoader } from "react-three-fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; const ThreeJSModal = () => { const [modalLoaded, setModalLoaded] = useState(false); const modalRef = useRef(); // Sử dụng useLoader để load file .jbx const gltf = useLoader(GLTFLoader, "/path/to/your/modal.jbx"); // Callback khi file đã được load const onModalLoaded = () => { setModalLoaded(true); }; return ( <> {modalLoaded && ( <> {/* Sử dụng OrbitControls để có thể quay vật thể */} <OrbitControls enableDamping dampingFactor={0.5} enableZoom={false} ref={modalRef} /> {/* Hiển thị vật thể */} <primitive object={gltf.scene} onReady={onModalLoaded} /> </> )} </> );
}; export default ThreeJSModal;

Trong đoạn code trên, chúng ta sử dụng useLoader để load file .jbx bằng GLTFLoader và useRef để lưu tham chiếu đến OrbitControls. OrbitControls cho phép người dùng xoay vật thể để xem nó từ nhiều góc độ khác nhau. Chúng ta sử dụng useState để theo dõi khi file đã được load và chỉ hiển thị vật thể khi file đã được load hoàn tất. Cuối cùng, chúng ta sử dụng primitive để hiển thị vật thể và onReady để đánh dấu khi file đã được load.

Sau khi đã tạo xong component, bạn có thể sử dụng nó trong ứng dụng React của mình bằng cách import và đưa nó vào trong DOM.

import ThreeJSModal from "./ThreeJSModal"; function App() { return ( <div> <ThreeJSModal /> </div> );
} export default App;

Chú ý rằng bạn cần phải thay đổi đường dẫn "/path/to/your/modal.jbx" để trỏ đúng đến file .jbx của bạn.

Kết hợp với texture riêng

Để kết hợp với texture riêng dạng png, bạn có thể sử dụng TextureLoader để load texture và gán nó vào vật thể sử dụng map trong Three.js.

Ví dụ, giả sử bạn có một texture là file "texture.png" trong thư mục public của ứng dụng của bạn. Bạn có thể sử dụng nó như sau:

import React, { useRef, useState } from "react";
import { useLoader } from "react-three-fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { TextureLoader } from "three/src/loaders/TextureLoader"; const ThreeJSModal = () => { const [modalLoaded, setModalLoaded] = useState(false); const modalRef = useRef(); // Sử dụng useLoader để load file .jbx const gltf = useLoader(GLTFLoader, "/path/to/your/modal.jbx"); // Sử dụng TextureLoader để load texture const texture = useLoader(TextureLoader, "/texture.png"); // Callback khi file đã được load const onModalLoaded = () => { setModalLoaded(true); }; return ( <> {modalLoaded && ( <> {/* Sử dụng OrbitControls để có thể quay vật thể */} <OrbitControls enableDamping dampingFactor={0.5} enableZoom={false} ref={modalRef} /> {/* Hiển thị vật thể và texture */} <primitive object={gltf.scene}> <meshStandardMaterial map={texture} /> </primitive> </> )} </> );
}; export default ThreeJSModal;

Trong ví dụ trên, chúng ta sử dụng TextureLoader để load file "texture.png". Sau đó, chúng ta gán texture này vào vật thể sử dụng map trong meshStandardMaterial. Bằng cách này, vật thể sẽ có texture "texture.png" kết hợp với file .jbx đã load.

Run animation của modal

Để chạy animation đầu tiên trong mảng animation của file .jbx, bạn có thể sử dụng useRef để tham chiếu đến vật thể của modal sau đó sử dụng phương thức mixer.clipAction() của AnimationMixer trong Three.js để chọn và chạy animation đầu tiên trong mảng animation.

Ví dụ, giả sử bạn có một file "modal.jbx" chứa một mảng các animation, và bạn muốn chạy animation đầu tiên trong mảng đó khi modal được tải lên, bạn có thể sử dụng mã sau:

import React, { useRef, useState, useEffect } from "react";
import { useLoader } from "react-three-fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; const ThreeJSModal = () => { const [modalLoaded, setModalLoaded] = useState(false); const modalRef = useRef(); const mixerRef = useRef(); // Sử dụng useLoader để load file .jbx const gltf = useLoader(GLTFLoader, "/path/to/your/modal.jbx"); // Callback khi file đã được load const onModalLoaded = () => { setModalLoaded(true); }; // Chạy animation đầu tiên khi modal được tải lên useEffect(() => { if (modalLoaded) { // Tìm animation đầu tiên trong mảng animation const [firstAnimation] = gltf.animations; // Khởi tạo mixer để chạy animation mixerRef.current = new THREE.AnimationMixer(modalRef.current); // Chọn animation đầu tiên và chạy nó const action = mixerRef.current.clipAction(firstAnimation); action.play(); } }, [modalLoaded]); return ( <> {modalLoaded && ( <> {/* Sử dụng OrbitControls để có thể quay vật thể */} <OrbitControls enableDamping dampingFactor={0.5} enableZoom={false} ref={modalRef} /> {/* Hiển thị vật thể */} <primitive object={gltf.scene} ref={modalRef} /> </> )} </> );
}; export default ThreeJSModal;

Trong ví dụ trên, chúng ta sử dụng useEffect để chạy animation đầu tiên trong mảng animation khi modal được tải lên. Đầu tiên, chúng ta tìm animation đầu tiên trong mảng animation bằng cách lấy phần tử đầu tiên trong mảng gltf.animations. Sau đó, chúng ta khởi tạo một AnimationMixer và sử dụng mixer.clipAction() để chọn và chạy animation đầu tiên.

Chúng ta cũng sử dụng useRef để tham chiếu đến vật thể của modal thông qua modalRef và tham chiếu đến AnimationMixer thông qua mixerRef.

Chạm để thay đổi animation

Để thay đổi animation khi người dùng nhấp vào modal 3D, bạn có thể sử dụng sự kiện onClick của mesh trong Three.js để chuyển đổi giữa các animation trong mảng gltf.animations của file .jbx.

Ví dụ, giả sử bạn có một file "modal.jbx" chứa một mảng các animation, và bạn muốn chuyển đổi giữa các animation khi người dùng nhấp vào modal, bạn có thể sử dụng mã sau:

import React, { useRef, useState, useEffect } from "react";
import { useLoader } from "react-three-fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; const ThreeJSModal = () => { const [modalLoaded, setModalLoaded] = useState(false); const modalRef = useRef(); const mixerRef = useRef(); const [animationIndex, setAnimationIndex] = useState(0); // Sử dụng useLoader để load file .jbx const gltf = useLoader(GLTFLoader, "/path/to/your/modal.jbx"); // Callback khi file đã được load const onModalLoaded = () => { setModalLoaded(true); }; // Chạy animation khi animationIndex thay đổi useEffect(() => { if (modalLoaded) { // Tìm animation tương ứng với animationIndex trong mảng animation const animation = gltf.animations[animationIndex]; // Chọn animation và chạy nó const action = mixerRef.current.clipAction(animation); action.play(); } }, [animationIndex]); // Sự kiện onClick để chuyển đổi giữa các animation const onClick = () => { setAnimationIndex((animationIndex + 1) % gltf.animations.length); }; return ( <> {modalLoaded && ( <> {/* Sử dụng OrbitControls để có thể quay vật thể */} <OrbitControls enableDamping dampingFactor={0.5} enableZoom={false} ref={modalRef} /> {/* Sử dụng sự kiện onClick để chuyển đổi giữa các animation */} <mesh onClick={onClick} ref={modalRef}> <primitive object={gltf.scene} /> </mesh> </> )} </> );
}; export default ThreeJSModal;

Trong ví dụ trên, chúng ta sử dụng useState để lưu trữ chỉ số của animation đang được chạy. Mỗi lần người dùng nhấp vào modal, chúng ta sẽ tăng chỉ số này lên một đơn vị và lấy phần dư với độ dài của mảng animation để chuyển đổi giữa các animation. Khi chỉ số animationIndex thay đổi, chúng ta sử dụng useEffect để chọn animation tương ứng từ mảng animation và chạy nó bằng mixer.clipAction().

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cùng tìm hiểu về các hook trong React hooks

Đối với ai đã từng làm việc với React thì chắc hẳn đã có những lúc cảm thấy bối rối không biết nên dùng stateless (functional) component hay là stateful component. Nếu có dùng stateful component thì cũng sẽ phải loay hoay với đống LifeCycle 1 cách khổ sở Rất may là những nhà phát triển React đã kịp

0 0 100

- vừa được xem lúc

Khi nào nên (và không nên) sử dụng Redux

. Công việc quản lý state với những hệ thống lớn và phức tạp là một điều khá khó khăn cho đến khi Redux xuất hiện. Lấy cảm hứng từ design pattern Flux, Redux được thiết kế để quản lý state trong các project JavaScript.

0 0 127

- vừa được xem lúc

ReactJS: Props và State

Nếu bạn đã học ReactJS hay React Native, bạn sẽ thấy các Props và State được sử dụng rất nhiều. Vậy chính xác chúng là gì? Làm thế nào để chúng ta sử dụng chúng đúng mục đích đây.

0 0 59

- vừa được xem lúc

State và Props trong Reactjs

Hello các bạn, tiếp tục seri tìm hiểu về ReactJs hôm nay mình xin giới thiệu đến các bạn hai thứ mình cho là thú vị nhất của ReactJs là State và Props. State bạn có thể hiểu đơn giản là một nơi mà bạn lưu trữ dữ liệu của Component, từ đó bạn có thể luân chuyển dữ liệu đến các thành phần trong Compon

0 0 54

- vừa được xem lúc

Memoization trong React

. 1.Introduction. Memoization có liên quan mật thiết đến bộ nhớ đệm, và dưới đây là một ví dụ đơn giản:. const cache = {}.

0 0 51

- vừa được xem lúc

Nâng cao hiệu suất React Hooks với React.memo, Memoization và Callback Functions

1.Ngăn Re-render và React.memo. React.

0 0 80