使用three.js 集成到react项目画旋转的地球

直接看效果 Konnect: For every human

上react组件

EarthComponent

import { useEffect, useRef } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import s from "./index.module.scss"
import earth4 from "@/assets/earth/earth4.jpg";
import earthBump from "@/assets/earth/earth_bump.jpg";
import earthSpec from "@/assets/earth/earth_spec.jpg";
import earthCloud from "@/assets/earth/earth_cloud.png";

export default function EarthComponent(props) {
    // 当前容器引用
    const curContainerRef = useRef(null);

    let scene, camera, renderer, controls;
    let WIDTH, HEIGHT, sphere, mesh_cloud;
    let requestAnimationFrameNum;
    // 初始化渲染
    function initRender() {
        WIDTH = props.width ?? window.innerWidth;
        HEIGHT = props.height ?? window.innerHeight;
        renderer = new THREE.WebGLRenderer({
            antialias: true,
        })
        renderer.setSize(WIDTH, HEIGHT);
        renderer.setPixelRatio(WIDTH / HEIGHT);
        renderer.physicallyCorrectLights = true;
        curContainerRef.current!.appendChild(renderer.domElement);
    }
    // 设置场景
    function initScene() {
        scene = new THREE.Scene();
        // 设置背景
        scene.background = new THREE.Color(0xff010811);
    }
    // 初始化相机
    function initCamera() {
        camera = new THREE.PerspectiveCamera(
            50,
            WIDTH / HEIGHT,
            1,
            10000,
        )
        camera.position.set(0, 0, 300);
        camera.minZoom = 1; // 设置最小缩放级别
        camera.maxZoom = 10; // 设置最大缩放级别

        controls = new OrbitControls(camera, renderer.domElement);
        // controls.enableDamping = true;
        // controls.dampingFactor = 1;
        // 禁止缩放
        controls.enableZoom = false;
    }
    // 初始化 环境光源
    function initLight() {
        //环境光
        // #4d4d4d
        const light = new THREE.AmbientLight(0x4d4d4d);
        scene.add(light);

        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
        directionalLight.position.set(100, 1000, 1000);
        scene.add(directionalLight);
        // #080820
        const light2 = new THREE.HemisphereLight(0xffffff, 0x080820, 0.5);
        scene.add(light2);
        //聚光灯
        const spotLight = new THREE.PointLight();
        spotLight.position.set(0, 0, 0);
        // spotLight.position.set(300, 100, 400);
        spotLight.angle = 45 * (Math.PI / 180);
        spotLight.castShadow = true;
        spotLight.shadow.mapSize.width = 1024;
        spotLight.shadow.mapSize.height = 1024;

        spotLight.shadow.camera.near = 500;
        spotLight.shadow.camera.far = 4000;
        spotLight.shadow.camera.fov = 30;

        scene.add(spotLight);
    }
    function initObject() {
        const tmap = new THREE.TextureLoader().load(earth4);
        const tbumpMap = new THREE.TextureLoader().load(earthBump);
        const tlarmap = new THREE.TextureLoader().load(earthSpec);
        const tcloud = new THREE.TextureLoader().load(earthCloud);

        let geometry = new THREE.SphereGeometry(90, 32, 32);
        let material = new THREE.MeshPhongMaterial();
        sphere = new THREE.Mesh(geometry, material);
        scene.add(sphere);
        material.map = tmap;
        /*凹凸贴图用于为材质增加厚度。我们用到的凹凸贴图是一张灰度图,当然你也可以使用彩色图。像素的密集程度定义的是凹凸的高度,
        但是凹凸图只包含像素的相对高度,没有任何倾斜的方向信息。所以使用凹凸贴图所能表达的深度信息有限。*/
        material.bumpMap = tbumpMap;
        material.bumpScale = 10;
        /*我们可以通过设置高光贴图来实现部分区域反光。通过设置高光贴图,我们会发现,只有海洋部分会有发光,而陆地部分没有高光的效果。 
        与 specular 配合使用*/
        material.specularMap = tlarmap;
        //添加高光颜色
        // #8cc2ff
        material.specular = new THREE.Color(0x8cc2ff);
        //specular高亮的程度,越高的值越闪亮。默认值为 30
        material.shininess = 3;

        //云层
        geometry = new THREE.SphereGeometry(92, 32, 32);
        //transparent png透明
        material = new THREE.MeshPhongMaterial({ map: tcloud, transparent: true });
        mesh_cloud = new THREE.Mesh(geometry, material);
        scene.add(mesh_cloud);
    }
    function init() {
        initRender();
        initScene();
        initCamera();
        initLight();
        initObject();
        animation();
    }
    function out() {
        try {

            cancelAnimationFrame(requestAnimationFrameNum);

            if (curContainerRef.current) {
                curContainerRef.current.innerHTML = "";
            }
            renderer = null;
        } catch (error) {
            console.log(error);
        }
    }
    function animation() {
        requestAnimationFrameNum = requestAnimationFrame(animation);
        renderer.render(scene, camera);
        sphere.rotation.y += 0.003;
        mesh_cloud.rotation.y += 0.003
        controls.update();
    }
    useEffect(() => {
        init()
        return () => {
            out();
        }
    }, []);

    return (
        
) }

样式文件 index.module.scss


.container {
    position: relative;
}

使用组件

import EarthComponent from "../EarthComponent"; 

图片资源

压缩包 

使用three.js 集成到react项目画旋转的地球_第1张图片使用three.js 集成到react项目画旋转的地球_第2张图片使用three.js 集成到react项目画旋转的地球_第3张图片

你可能感兴趣的:(javascript,react.js,前端)