Danh mục 3D
Giao diện
Bây giờ chúng ta đã hoàn thành chính yếu cảnh 3D của mình, ta có thể bắt đầu làm việc trên giao diện HTML.
Hãy tạo một component Interface.jsx
với cùng 4 phần như cảnh 3D của chúng ta:
export const Interface = () => { return ( <div className="interface"> <div className="sections"> {/* HOME */} <section className="section section--bottom">HOME</section> {/* SKILLS */} <section className="section section--right">SKILLS</section> {/* PROJECTS */} <section className="section section--left">PROJECTS</section> {/* CONTACT */} <section className="section section--left">CONTACT</section> </div> </div> ); };
Chúng ta sẽ sử dụng các lớp section--bottom
, section--right
và section--left
để định vị nội dung bên trong các phần.
Hiện tại chúng ta chỉ thêm tên các phần, chúng ta sẽ thêm nội dung sau.
Hãy thêm component Interface
của chúng ta vào component App
:
import { Scroll, ScrollControls } from "@react-three/drei"; import { Canvas } from "@react-three/fiber"; import { MotionConfig } from "framer-motion"; import { Experience } from "./components/Experience"; import { config } from "./config"; import { Interface } from "./components/Interface"; function App() { return ( <> <Canvas camera={{ position: [0, 0.5, 5], fov: 42 }}> <color attach="background" args={["#f5f3ee"]} /> <fog attach="fog" args={["#f5f3ee", 10, 50]} /> <ScrollControls pages={config.sections.length} damping={0.1} maxSpeed={0.2} > <group position-y={-1}> <MotionConfig transition={{ duration: 0.6, }} > <Experience /> </MotionConfig> </group> <Scroll html> <Interface /> </Scroll> </ScrollControls> </Canvas> </> ); } export default App;
Để tạo kiểu cho giao diện HTML của chúng ta, chúng ta sẽ sử dụng CSS thuần để có thể chung nhất có thể. Bạn có thể sử dụng framework CSS yêu thích của mình nếu muốn. (Tôi đã sử dụng TailwindCSS cho hầu hết các dự án của tôi)
Hãy thêm các kiểu mặc định vào tệp index.css
của chúng ta:
@import url("https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;700&display=swap"); :root { --primary-color: #4668ee; --text-color: #1a202c; --text-light-color: #555; } #root { width: 100vw; height: 100vh; } body { margin: 0; font-family: "Roboto Slab", serif; } /* ... */ .interface { width: 100vw; display: flex; flex-direction: column; align-items: center; } .sections { max-width: 1200px; width: 100%; } .section { height: 100vh; display: flex; justify-content: center; align-items: center; } .section--top { align-items: flex-start; } .section--bottom { align-items: flex-end; } .section--right { justify-content: flex-end; } .section--left { justify-content: flex-start; }
Chúng ta đã nhập font Roboto Slab từ Google Fonts và định nghĩa một số biến màu sắc.
Container của các phần được căn giữa và có max-width
là 1200px
để giữ độ dễ đọc tốt trên màn hình lớn.
Các phần có height
là 100vh
(chiều cao đầy đủ) và mặc định được căn giữa. Chúng ta sẽ sử dụng các lớp section--top
, section--bottom
, section--right
và section--left
để định vị nội dung bên trong các phần.
Giao diện của chúng ta đã sẵn sàng, hãy thêm nội dung nào!
Chỉ báo cuộn phần đầu
Ở phần đầu, chúng ta sẽ thêm một chỉ báo cuộn để thông báo cho người dùng rằng họ có thể cuộn để xem các phần khác.
Đầu tiên, hãy tạo một state để biết liệu người dùng đã cuộn hay chưa:
import { useScroll } from "@react-three/drei"; import { useFrame } from "@react-three/fiber"; import { useState } from "react"; export const Interface = () => { const scrollData = useScroll(); const [hasScrolled, setHasScrolled] = useState(false); useFrame(() => { setHasScrolled(scrollData.offset > 0); }); // ... };
Sau đó, trong phần đầu, chúng ta có thể thêm một motion.div
với một đối tượng variants
để tạo một chỉ báo cuộn có thể nhìn thấy:
// ... import { motion } from "framer-motion"; export const Interface = () => { // ... return ( <div className="interface"> <div className="sections"> {/* HOME */} <section className="section section--bottom"> <motion.div className="scroll-down" initial={{ opacity: 0, }} animate={{ opacity: hasScrolled ? 0 : 1, }} > <motion.div className="scroll-down__wheel" initial={{ translateY: 0, }} animate={{ translateY: 4, }} transition={{ duration: 0.4, repeatDelay: 0.5, repeatType: "reverse", repeat: Infinity, }} ></motion.div> </motion.div> </section> {/* ... */} </div> </div> ); };
Chúng ta đang sử dụng framer motion để tạo hiệu ứng động cho độ mờ và vị trí bánh xe. Để làm cho bánh xe di chuyển lên và xuống, chúng ta sử dụng các thuộc tính repeat
và repeatType
.
React Three Fiber: The Ultimate Guide to 3D Web Development
✨ You have reached the end of the preview ✨
Go to the next level with Three.js and React Three Fiber!
Get full access to this lesson and the complete course when you enroll:
- 🔓 Full lesson videos with no limits
- 💻 Access to the final source code
- 🎓 Course progress tracking & completion
- 💬 Invite to our private Discord community
One-time payment. Lifetime updates included.