react-three-fiber入门项目(1)-组件化设计

系列文章目录

1. three.js入门知识点资料整理



前言

Global Warming项目是基于react框架写的threejs项目,本文将记录从html+threejs嵌入react fiber框架中的过程。


一、项目效果图

在这里插入图片描述
背景中的地球仪将绕着y轴匀速转动。

二、细说代码部分

1.拆分组件

效果图分成两部分:
将地球的材质贴图放在arc文件下的textures文件中,component文件下放结果图拆分出来的两个组件。
在这里插入图片描述

  1. 地球仪earth
    在这里插入图片描述

  2. 文字topSection
    在这里插入图片描述

最终,将component汇集在App.jsx中,以下是App.jsx的代码。

  • js和jsx不同,jsx的全称为 JavaScript XML。
  • react定义的一种类似于XML的JS扩展语法: JS + XML本质是React.createElement(component, props, ...children)方法的语法糖。
  • 作用: 用来简化创建虚拟DOM。
import "./App.css";
import styled from "styled-components";
import { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import { Earth } from "./components/earth";
import { TopSection } from "./components/topSection";

//CanvasContainer样式
const CanvasContainer = styled.div`
  width: 100%;
  height: 100%;
`;

function App() {
  return (
    // Canvas容器
    <CanvasContainer>
      <TopSection />
      
      <Canvas>
        {/* loading的时候:加载状态 */}
        <Suspense fallback={null}>
          <Earth />
        </Suspense>
      </Canvas>

    </CanvasContainer>
  );
}

export default App;

Canvas 组件在幕后做了一些重要的设置工作:

  • 它设置了一个Scene和一个Camera,这是渲染所需的基本构建块
  • 它会自动处理调整大小
  • 它每一帧都渲染我们的场景

细节:

  • 可以通过修改const CanvasContainer = styled.div…`中的代码,进而实现修改canvas容器的样式。
  • 通过<TopSection />引入文字部分内容。
  • <Canvas>中包含的内容:
    1. <Suspense fallback={null}>:表示在页面加载过程中呈现的状态,在null位置可以填入自定义的loading页面设计。
    2. 通过<Earth />引入地球仪部分。

此处参考博客:使用react-three-fiber加载glb格式3D文件,并播放3D模型自带动画


2.地球仪部分(重点)

代码如下(示例):

import React, { useRef } from "react";
import { useFrame, useLoader } from "@react-three/fiber";
import { OrbitControls, Stars } from "@react-three/drei";
import * as THREE from "three";

import EarthDayMap from "../../assets/textures/8k_earth_daymap.jpg";
import EarthNormalMap from "../../assets/textures/8k_earth_normal_map.jpg";
import EarthSpecularMap from "../../assets/textures/8k_earth_specular_map.jpg";
import EarthCloudsMap from "../../assets/textures/8k_earth_clouds.jpg";
import { TextureLoader } from "three";



export function Earth(props) {
  // 加载材质图
  const [colorMap, normalMap, specularMap, cloudsMap] = useLoader(
    TextureLoader,
    [EarthDayMap, EarthNormalMap, EarthSpecularMap, EarthCloudsMap]
  );

// 
  const earthRef = useRef();
  const cloudsRef = useRef();

  useFrame(({ clock }) => {
    const elapsedTime = clock.getElapsedTime();

    earthRef.current.rotation.y = elapsedTime / 6;
    cloudsRef.current.rotation.y = elapsedTime / 6;
  });


  return (
    <>
    {/* 光强度:太阳,无处不在的光 */}
      <ambientLight intensity={1} />
      {/* 点光 */}
      <pointLight color="#f6f3ea" position={[2, 0, 5]} intensity={1.2} />
      <Stars
        radius={300}
        depth={60}
        count={20000}
        factor={7}
        saturation={0}
        fade={true}
      />
      <mesh ref={cloudsRef} position={[0, 0, 3]}>
        <sphereGeometry args={[1.005, 32, 32]} />
        {/* 光亮表面的材质 */}
        <meshPhongMaterial  
          map={cloudsMap}
          opacity={0.4}
          depthWrite={true}
          transparent={true}
          side={THREE.DoubleSide}
        />
        {/* 叠加 */}
      </mesh>
      <mesh ref={earthRef} position={[0, 0, 3]}>
        <sphereGeometry args={[1, 32, 32]} />
        <meshPhongMaterial specularMap={specularMap} />
        <meshStandardMaterial
          map={colorMap}
          normalMap={normalMap}
          metalness={0.4}
          roughness={0.7}
        />
        {/* <OrbitControls
          enableZoom={true}
          enablePan={true}
          enableRotate={true}
          zoomSpeed={0.6}
          panSpeed={0.5}
          rotateSpeed={0.4}
        /> */}
      </mesh>
    </>
  );
}

细节:

  • three.js拥有的组件,放在react中以标签形式出现,且一律小写。
  • 加载材质图:
    2.1 通过import 别名 from "url"引入图片;
    2.2 通过加载器useLoader(加载器类型,[…加载内容])
  • useRef:
    此处涉及到react三大组件之一的ref。参考博客:react中ref的使用

reference表示引用。

  • 使用场景:直接使用dom元素的某个方法,或者直接使用自定义组件中的某个方法。
  • 功能:
  1. 作用于内置的html组件,得到的是真实的dom
  2. ref作用于类组件,得到的是类的实例
  3. ref不能作用于函数组件
  1. useFrame:专注于动画渲染。

  2. Stars:将基于着色器的星空添加到场景中。这是brei自带的组件。官网文档如图所示。其中包含的参数有,radius=半径;depth=深度;count=数量;factor=因子;saturation=饱和度;fade speed=衰减速度。
    在这里插入图片描述

  3. mesh:
    网格就是一系列的多边形组成的,三角形或者四边形,网格一般由顶点来描绘,我们看见的三维开发的模型就是由一系列的点组成的。
    几何体是不能被渲染的,只有几何体和材质结合成网格才能被渲染到屏幕上。


3. 文字部分

import React from "react";
import styled from "styled-components";

const TopSectionContainer = styled.div`
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-color: #1756dd32;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 13%;
  z-index: 99;
`;

const Logo = styled.h1`
  margin: 0;
  color: #fff;
  font-weight: 800;
  font-size: 80px;
`;

const Slogan = styled.h4`
  margin: 0;
  color: #fff;
  font-weight: 700;
  font-size: 30px;
  margin-top: 10px;
`;

const Paragraph = styled.p`
  margin: 0;
  margin-top: 3em;
  color: #fff;
  font-size: 14px;
  line-height: 1.5;
  font-weight: 500;
  max-width: 30%;
  text-align: center;
`;

const DonateButton = styled.button`
  outline: none;
  border: none;
  background-color: #27b927;
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  border-radius: 8px;
  padding: 8px 2em;
  margin-top: 3em;
  cursor: pointer;
  border: 2px solid transparent;
  transition: all 350ms ease-in-out;

  &:hover {
    background-color: transparent;
    border: 2px solid #27b927;
  }
`;

const MadeBy = styled.h3`
  color: #fff;
  position: fixed;
  bottom: 5px;
  left: 50%;
  transform: translateX(-50%);
`;

export function TopSection() {
  return (
    <TopSectionContainer>
      <Logo>Global Warming</Logo>
      <Slogan>Keep it cool for safe living</Slogan>
      <Paragraph>
        You can help us cool off our world and have it go back to it's best
        state ever by donating to help fix our only world and our beloved EARTH!
        Be cool and let the earth be cool. Let the ice burgs to live. Globe is
        warming and will set to fire. Stop polluting, it will cost extra.
      </Paragraph>
      <DonateButton>Donate</DonateButton>
      {/* <MadeBy>
        <u>Made By:</u> Islem Maboud
      </MadeBy> */}
    </TopSectionContainer>
  );
}

细节:

  • 使用自定义标签时注意首字母大写;
  • 通过styled.标明css标签,并定义样式;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值