forked from tongChong/BingDwenDwen
feat: 数字城市示例增加入场相机动画、添加加载进度显示.
This commit is contained in:
parent
904825aa5c
commit
9190ee71b0
|
|
@ -0,0 +1,44 @@
|
|||
import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";
|
||||
|
||||
const Animations = {
|
||||
//相机移动实现漫游等动画
|
||||
animateCamera: (camera, controls, newP, newT, time = 2000, callBack) => {
|
||||
console.log(camera, controls, newP, newT)
|
||||
var tween = new TWEEN.Tween({
|
||||
x1: camera.position.x, // 相机x
|
||||
y1: camera.position.y, // 相机y
|
||||
z1: camera.position.z, // 相机z
|
||||
x2: controls.target.x, // 控制点的中心点x
|
||||
y2: controls.target.y, // 控制点的中心点y
|
||||
z2: controls.target.z, // 控制点的中心点z
|
||||
});
|
||||
console.log(tween)
|
||||
tween.to({
|
||||
x1: newP.x,
|
||||
y1: newP.y,
|
||||
z1: newP.z,
|
||||
x2: newT.x,
|
||||
y2: newT.y,
|
||||
z2: newT.z,
|
||||
},
|
||||
time
|
||||
);
|
||||
tween.onUpdate(function (object) {
|
||||
camera.position.x = object.x1;
|
||||
camera.position.y = object.y1;
|
||||
camera.position.z = object.z1;
|
||||
controls.target.x = object.x2;
|
||||
controls.target.y = object.y2;
|
||||
controls.target.z = object.z2;
|
||||
controls.update();
|
||||
});
|
||||
tween.onComplete(function () {
|
||||
controls.enabled = true;
|
||||
console.log('complete')
|
||||
callBack();
|
||||
});
|
||||
tween.easing(TWEEN.Easing.Cubic.InOut);
|
||||
tween.start();
|
||||
},
|
||||
}
|
||||
export default Animations;
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#loading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background: #582424;
|
||||
background: -webkit-linear-gradient(to right, #97444f, #582424);
|
||||
background: linear-gradient(to right, #97444f, #582424);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
font-size: 64px;
|
||||
color: #FFFFFF;
|
||||
text-shadow: 0 1px 0 hsl(174,5%,80%),
|
||||
0 2px 0 hsl(174,5%,75%),
|
||||
0 3px 0 hsl(174,5%,70%),
|
||||
0 4px 0 hsl(174,5%,66%),
|
||||
0 5px 0 hsl(174,5%,64%),
|
||||
0 6px 0 hsl(174,5%,62%),
|
||||
0 7px 0 hsl(174,5%,61%),
|
||||
0 8px 0 hsl(174,5%,60%),
|
||||
0 0 5px rgba(0,0,0,.05),
|
||||
0 1px 3px rgba(0,0,0,.2),
|
||||
0 3px 5px rgba(0,0,0,.2),
|
||||
0 5px 10px rgba(0,0,0,.2),
|
||||
0 10px 10px rgba(0,0,0,.2),
|
||||
0 20px 20px rgba(0,0,0,.3);
|
||||
}
|
||||
|
|
@ -5,6 +5,9 @@ import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";
|
|||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
|
||||
import Stats from "three/examples/jsm/libs/stats.module";
|
||||
import cityModel from './models/city.fbx';
|
||||
import Animations from './animations';
|
||||
import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";
|
||||
import './index.css';
|
||||
|
||||
export default class City extends React.Component {
|
||||
|
||||
|
|
@ -12,6 +15,11 @@ export default class City extends React.Component {
|
|||
super(props);
|
||||
}
|
||||
|
||||
state = {
|
||||
// 页面模型加载进度,0:未加载,100:加载完成
|
||||
loadingProcess: 0
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.initThree()
|
||||
}
|
||||
|
|
@ -19,14 +27,15 @@ export default class City extends React.Component {
|
|||
initThree = () => {
|
||||
var container, controls, stats;
|
||||
var camera, scene, renderer, light, cityMeshes = [];
|
||||
let _this = this;
|
||||
init();
|
||||
animate();
|
||||
function init() {
|
||||
container = document.getElementById('container');
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.shadowMap.enabled = true;
|
||||
container = document.getElementById('container');
|
||||
container.appendChild(renderer.domElement);
|
||||
// 场景
|
||||
scene = new THREE.Scene();
|
||||
|
|
@ -34,7 +43,7 @@ export default class City extends React.Component {
|
|||
scene.fog = new THREE.Fog(0xeeeeee, 0, 100);
|
||||
// 透视相机:视场、长宽比、近面、远面
|
||||
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||
camera.position.set(0, 10, 20);
|
||||
camera.position.set(120, 100, 100);
|
||||
camera.lookAt(new THREE.Vector3(0, 0, 0));
|
||||
// 半球光源:创建室外效果更加自然的光源
|
||||
const cubeGeometry = new THREE.BoxGeometry(0.001, 0.001, 0.001);
|
||||
|
|
@ -71,7 +80,7 @@ export default class City extends React.Component {
|
|||
|
||||
// 加载模型
|
||||
var loader = new FBXLoader();
|
||||
loader.load(cityModel, function (mesh) {
|
||||
loader.load(cityModel, mesh => {
|
||||
mesh.traverse(function (child) {
|
||||
if (child.isMesh) {
|
||||
child.castShadow = true;
|
||||
|
|
@ -84,6 +93,13 @@ export default class City extends React.Component {
|
|||
mesh.position.set(40, 0, -50);
|
||||
mesh.scale.set(1, 1, 1);
|
||||
scene.add(mesh);
|
||||
}, res => {
|
||||
if (Number((res.loaded / res.total * 100).toFixed(0)) === 100) {
|
||||
Animations.animateCamera(camera, controls, { x: 0, y: 10, z: 20 }, { x: 0, y: 0, z: 0 }, 4000, () => {});
|
||||
}
|
||||
_this.setState({ loadingProcess: Math.floor(res.loaded / res.total * 100) });
|
||||
}, err => {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
controls = new OrbitControls(camera, renderer.domElement);
|
||||
|
|
@ -105,6 +121,7 @@ export default class City extends React.Component {
|
|||
requestAnimationFrame(animate);
|
||||
renderer.render(scene, camera);
|
||||
stats && stats.update();
|
||||
TWEEN && TWEEN.update();
|
||||
}
|
||||
|
||||
// 增加点击事件,声明raycaster和mouse变量
|
||||
|
|
@ -127,7 +144,15 @@ export default class City extends React.Component {
|
|||
|
||||
render () {
|
||||
return (
|
||||
<div id="container"></div>
|
||||
<div>
|
||||
<div id="container"></div>
|
||||
{this.state.loadingProcess === 100 ? '' : (
|
||||
<div id="loading">
|
||||
<div className="box">{this.state.loadingProcess} %</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue