React集成Cesium+ThreeJs流程汇总
集成Cesium+ThreeJS
在 React集成Cesium流程汇总 已经集成好Cesium的基础上集成ThreeJS
1.安装ThreeJS模块
1)执行yarn add three 安装ThreeJS模块:
yarn add three
2)因为项目基于TypeScript进行构建,需要按装three 的声明文件,执行命令:
yarn add typescript @types/three 或者
npm i --save-dev @types/three
2.创建CesiumForThreeJS组件
在 src-> components->CesiumForThree目录下创建 CesiumForThree.js 文件 并写入如下内容:
CesiumForThree.js
import React,{Component} from 'react';
import './CesiumForThree.css';
//引入Three.js
import * as THREE from "three"
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
//引入cesium
import 'cesium/Widgets/widgets.css'
var Cesium = require('cesium/Cesium');
class CesiumForThree extends Component {
state={
viewer:null,
scene:null,
camera:null,
renderer:null
}
componentDidMount() {
var viewer = new Cesium.Viewer('cesiumContainer', {
selectionIndicator: false,
animation: false,
baseLayerPicker: false,
geocoder: false,
timeline: false,
sceneModePicker: false,
navigationHelpButton: false,
infoBox: false,
fullscreenButton: false,
homeButton: false,
imageryProvider:new Cesium.UrlTemplateImageryProvider({
url : "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
name: "openstreetmap",
subdomains: ["a", "b", "c", "d"],
format: "image/jpeg",
tileMatrixSetID:"GoogleMapsCompatible",
minimumLevel:1,
maximumLevel:20
})
});
viewer.bottomContainer.style.display = "none"; //隐藏图标
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.scene.debugShowFramesPerSecond = true;
let center = Cesium.Cartesian3.fromDegrees(114.052652, 22.501094,2000);
viewer.camera.setView({//flyTo
destination: center,
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-60),
roll: Cesium.Math.toRadians(0)
},
duration: 3
});
this.loadThree(viewer);
this.state.viewer=viewer;
this.loop();
}
loadThree=(viewer)=>{
let fov = 45;
let width = window.innerWidth;
let height = window.innerHeight;
let aspect = width / height;
let near = 1;
let far = 10 * 1000 * 1000;
var scene = new THREE.Scene();//Scene
// fov — 摄像机视锥体垂直视野角度
// aspect — 摄像机视锥体长宽比
// near — 摄像机视锥体近端面
// far — 摄像机视锥体远端面
var camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer({
antialias: true,// 开启抗锯齿
alpha: true,// canvas是否包含alpha (透明度)。默认为 false
});//渲染场景
var pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
viewer.cesiumWidget.canvas.parentElement.appendChild(renderer.domElement);
viewer.cesiumWidget.canvas.parentElement.appendChild(renderer.domElement);
this.addModel(scene);
this.state.scene=scene;
this.state.camera=camera;
this.state.renderer=renderer;
}
addModel=(scene)=>{
// 加载 glTF 格式的模型
let loader = new GLTFLoader(); /*实例化加载器*/
const group = new THREE.Group();//实体容器
//http://127.0.0.1:8066/PubData/MainBuilding/SM_AC_FNGC_1.gltf
// http://127.0.0.1:8066/PubData/ThreeModel/models/gltf/Xbot.glb/
var model="http://127.0.0.1:8066/PubData/MainBuilding/SM_AC_FNGC_1.gltf";
var model01="http://127.0.0.1:8066/PubData/ThreeModel/models/gltf/DamagedHelmet/glTF/DamagedHelmet.gltf";
var model02="http://127.0.0.1:8066/WebServer/three.js-r136/examples/models/gltf/IridescentDishWithOlives.glb";
var model03="http://127.0.0.1:8066/PubData/ThreeModel/models/gltf/MaterialsVariantsShoe/glTF/MaterialsVariantsShoe.gltf";
// loader.setDecoderPath( '/examples/js/libs/draco/' );
loader.load(model, function(gltf) {
let GroupS = new THREE.Group();
var model = gltf.scene;
// Three.scene.add( model );
model.traverse( function ( child ) {
if (child instanceof THREE.Mesh){
//设置模型生成阴影并接收阴影
child.castShadow = true;
child.receiveShadow = true;
}
});
// model.castShadow = true;
// model.receiveShadow = true;
let centerHigh = Cesium.Cartesian3.fromDegrees(114.052652, 22.509394,0);
model.position.set(centerHigh.x,centerHigh.y,centerHigh.z);
model.translateX(-20);//沿着x轴正方向平移距离100
model.translateZ(-20);//沿着x轴正方向平移距离100
// var axis = new THREE.Vector3(031,0);//向量axis
// model.rotateOnAxis(axis,2);//绕axis3旋转π/8
// model.rotateX(Math.PI/4)3
model.rotateY(3.55);//水平旋转 越大逆时针 反正 z
model.rotateX(-0.23);//水平旋转 越大逆时针 反正 Y
model.rotateZ(-0.53);//X
scene.add( model );
//点聚光===================
let center33 = Cesium.Cartesian3.fromDegrees(114.052970,22.509301,100);
const light = new THREE.PointLight( 0xffffff, 8, 150);
light.position.copy(center33);
// light.position.set( 15, 40, 35 );
light.castShadow = false; // default false
scene.add( light );
light.shadow.mapSize.width = 15; // default
light.shadow.mapSize.height = 12; // default
light.shadow.camera.near = 1.5; // default
light.shadow.camera.far = 10 // default
}, function(xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
}, function(error) {
console.log('load error!' + error.getWebGLErrorMessage());
})
}
// 同步
loop=()=>{
var viewer=this.state.viewer;
var camera=this.state.camera;
var scene=this.state.scene;
var renderer=this.state.renderer;
let cesiumContainer = document.getElementById("cesiumContainer");
requestAnimationFrame(this.loop);//告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
//该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
// 1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
// 2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
// stats.update();
viewer.render();//渲染场景。除非设置为 false,否则将自动调用此函数;
//用 Cesium 注册 Three.js 场景
camera.fov = Cesium.Math.toDegrees(viewer.camera.frustum.fovy) // 将three试图的中心 赋值等于Cesium 试图的中心
//three.camera.updateProjectionMatrix();
// Clone Cesium Camera projection position so the
// Three.js Object will appear to be at the same place as above the Cesium Globe
camera.matrixAutoUpdate = false;//矩阵自动更新
let cvm = viewer.camera.viewMatrix;
let civm = viewer.camera.inverseViewMatrix;
// 注意这里,经大神博客得知,three高版本这行代码需要放在 three.camera.matrixWorld 之前
// Three.camera.lookAt(0, 0, 0);
camera.matrixWorld.set(
civm[0], civm[4], civm[8], civm[12],
civm[1], civm[5], civm[9], civm[13],
civm[2], civm[6], civm[10], civm[14],
civm[3], civm[7], civm[11], civm[15]
);
camera.matrixWorldInverse.set(
cvm[0], cvm[4], cvm[8], cvm[12],
cvm[1], cvm[5], cvm[9], cvm[13],
cvm[2], cvm[6], cvm[10], cvm[14],
cvm[3], cvm[7], cvm[11], cvm[15]
);
// 设置three宽高
let width = cesiumContainer.clientWidth;
let height = cesiumContainer.clientHeight;
let aspect = width / height;
camera.aspect = aspect;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
renderer.clear();
renderer.render(scene,camera);
}
render() {
return (
<div className='container-integrate'>
{/* cesium容器*/}
<div id="cesiumContainer" className='cesiumContainer'></div>
</div>
);
}
}
export default CesiumForThree
在 src-> pages-> Home->Home.tsx 处引入Three组件 代码如下:
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Button } from 'antd';
import CesiumForThree from '../../components/CesiumForThree/CesiumForThree';
function MyButton() {
let navigate = useNavigate();
function handleClick() {
navigate('/Index');
};
return <button onClick={handleClick}>Submit</button>;
};
class Home extends React.Component{
render(){
return(
<div>
<Button type="primary">Home页面</Button>
<MyButton></MyButton>
<CesiumForThree></CesiumForThree>
</div>
)
}
}
export default Home
3.运行查看效果
控制台输入命令 yarn start
浏览器打开显示如上图所示
总结
以上就是React集成Cesium+ThreeJs的内容了。
源代码打包-> React集成Cesium+ThreeJs示例代码