Babylonjs 加载Gltf模型添加动画、点击事件、天空盒、标签
加载Gltf模型方法、模型点击事件、label标签、天空盒
import React, { useState, useEffect, useRef } from 'react'
import TWEEN from '@tweenjs/tween.js'
import { useNavigate } from "react-router-dom"
import Images from '../img/index'
const BABYLON = window.BABYLON
function Home() {
const navigate = useNavigate();
const isClient = typeof window === 'object';
const lastWidth = useRef();
function getSize() {
return {
width: isClient ? window.innerWidth : undefined
}
}
const [windowSize, setWindowSize] = useState(getSize);
// Listen for page size changes
useEffect(() => {
//Exit if not user/browser
if (!isClient) { return false }
function handleResize() {
if (window?.innerWidth !== lastWidth.current) {
const width = getSize();
lastWidth.current = width;
setWindowSize(width);
}
}
window.addEventListener('resize', handleResize);
})
let interval = useRef(null);
let [date, setDate] = useState('');
let [week, setWeek] = useState('');
let [time, setTime] = useState('');
let [refresh, setRefresh] = useState('');
let [currentTitle, setCurrentTitle] = useState('');
// Time display
useEffect(() => {
// Year-Month-Day
let date = new Date();
let year = date.getFullYear();
let month = date.getMonth() 1;
month > 9 ? month = month : month = '0' month;
let day = date.getDate();
day > 9 ? day = day : day = '0' day;
let str1 = year '.' month '.' day;
setDate(str1);
// Week
let week = date.getDay();
switch (week) {
case 0:
week = '星期日';
break;
case 1:
week = '星期一';
break;
case 2:
week = '星期二';
break;
case 3:
week = '星期三';
break;
case 4:
week = '星期四';
break;
case 5:
week = '星期五';
break;
case 6:
week = '星期六';
break;
default:
week = '';
break;
}
setWeek(week);
// Hours-Minute-Second
let hours = date.getHours();
hours > 9 ? hours = hours : hours = '0' hours;
let minutes = date.getMinutes();
minutes > 9 ? minutes = minutes : minutes = '0' minutes;
let str2 = hours ':' minutes;
setTime(str2);
// Refresh Time
interval.current = setInterval(() => {
setRefresh(Math.random());
}, 1000)
}, [refresh])
// Model loading
useEffect(() => {
// Get canvas dom object
var canvas = document.getElementById('cvs');
// Init 3d engine
var engine = new BABYLON.Engine(canvas, true);
// Create scene (callback object)
var createScene = function () {
// Create scene object
var scene = new BABYLON.Scene(engine);
// Create camera
var camera = new BABYLON.ArcRotateCamera("Camera", 30, Math.PI / 2.06, 120, BABYLON.Vector3.Zero(), scene);
// Zoom speed
camera.wheelPrecision = 1.8;
// Camera event
camera.attachControl(canvas, true);
// Create light
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
// Set background opacity
scene.clearColor = new BABYLON.Color4(0, 0, 0, 0);
// Create skybox
var skybox = BABYLON.Mesh.CreateBox("skyBox", 6000.0, scene);
var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("TropicalSunnyDay/TropicalSunnyDay", scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.disableLighting = true;
skybox.material = skyboxMaterial;
// Create ground
// var groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);
// groundMaterial.diffuseTexture = new BABYLON.Texture("img/diff2.jpg", scene);
// groundMaterial.diffuseTexture.uScale = groundMaterial.diffuseTexture.vScale = 1;
// var ground = BABYLON.Mesh.CreateGround("ground", 6000, 6000, 1, scene, false);
// ground.position.y = -3;
// ground.material = groundMaterial;
// Gltf loading
BABYLON.SceneLoader.Append("/gltf/", "zhny1.gltf", scene, function (scene) {
var meshes = scene.meshes;
// Identify model array
let ztsz = [];
// Text and panel to be deleted
let rmbabelbuild = [];
// GUI draw model label tips
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("ui1");
advancedTexture.renderScale = 1;
// Draw func
function createLabel(mesh, labelname) {
var label = new BABYLON.GUI.Rectangle("label for " labelname);
label.background = "rgba(0, 0, 0, 1)";
label.height = "60px";
label.alpha = 0.6;
label.width = "300px";
label.cornerRadius = 20;
label.thickness = 1;
label.linkOffsetY = -100;
advancedTexture.addControl(label);
label.linkWithMesh(mesh);
var text1 = new BABYLON.GUI.TextBlock();
text1.text = labelname;
text1.color = "white";
label.addControl(text1);
rmbabelbuild.push(label);
rmbabelbuild.push(text1);
}
// Remove draw label
function removeLabel(arr) {
for (let i = 0; i < arr.length; i ) {
arr[i].dispose();
}
rmbabelbuild = [];
}
// Set model click event func
function clickModel(index, model, name, code) {
if (index > -1) {
model.actionManager = new BABYLON.ActionManager(scene);
model.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(
BABYLON.ActionManager.OnLeftPickTrigger,
function (event) {
const sourceBox = event.meshUnderPointer;
console.log('current click model %o', sourceBox);
// Set camera
camera.lockedTarget = sourceBox;
// Set left content and right content display
let rightContent = document.getElementById('right');
let leftContent = document.getElementById('left');
rightContent.style.display = "flex";
leftContent.style.display = "flex";
// Show animation - tweenjs
var coords = { x: 0, y: 0 };
var tween = new TWEEN.Tween(coords)
.to({ x: 416, y: 895 }, 1000)
.easing(TWEEN.Easing.Quadratic.Out)
.onUpdate(function () {
leftContent.style.setProperty('width', coords.x 'px');
rightContent.style.setProperty('width', coords.x 'px');
})
.start();
animate();
function animate() {
requestAnimationFrame(animate);
TWEEN.update();
}
setCurrentTitle(name)
// Show vertebral body
for (let i = 0; i < ztsz.length; i ) {
ztsz[i].visibility = false;
}
ztsz[code].visibility = true;
ztsz[code 1].visibility = true;
ztsz[code 2].visibility = true;
// Vertebrum beat animation
const frameRate = 1;
const xSlide = new BABYLON.Animation("xSlide", "position.y", frameRate, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
const keyFrames = [];
// Keyframes
keyFrames.push({
frame: 0,
value: 1,
});
keyFrames.push({
frame: frameRate,
value: 0,
});
keyFrames.push({
frame: 2 * frameRate,
value: 1,
});
xSlide.setKeys(keyFrames);
// Play animation
ztsz[code].animations.push(xSlide);
scene.beginAnimation(ztsz[code], 0, 2 * frameRate, true);
removeLabel(rmbabelbuild);
createLabel(ztsz[code], name);
}
)
);
}
}
// Add click event
for (let i = 0; i < meshes.length; i ) {
// Hide initial flag
if (meshes[i].id.indexOf("锥体") !== -1) {
meshes[i].visibility = false;
ztsz.push(meshes[i]);
}
// 东大220kv全感知智能变电站
let bdz = meshes[i].id.indexOf('平面.027');
clickModel(bdz, meshes[i], '智能变电站', 15);
// 集中式储能电站
let ldcn = meshes[i].id.indexOf('立方体.007');
clickModel(ldcn, meshes[i], '集中式储能电站', 12);
// 梯次利用储能电站
let fbsgf = meshes[i].id.indexOf('平面.023');
clickModel(fbsgf, meshes[i], '梯次利用储能电站', 3);
// 分布式能源站
let fbsnyz = meshes[i].id.indexOf('平面.013');
clickModel(fbsnyz, meshes[i], '分布式能源站', 0);
// 绿色新型数据中心
let sjzx = meshes[i].id.indexOf('立方体.004');
clickModel(sjzx, meshes[i], '绿色新型数据中心', 9);
// 分布式光伏
let fbsgf1 = meshes[i].id.indexOf('平面.003');
clickModel(fbsgf1, meshes[i], '分布式光伏', 6);
let fbsgf2 = meshes[i].id.indexOf('平面.005');
clickModel(fbsgf2, meshes[i], '分布式光伏', 6);
let fbsgf3 = meshes[i].id.indexOf('平面.014');
clickModel(fbsgf3, meshes[i], '分布式光伏', 6);
let fbsgf4 = meshes[i].id.indexOf('平面.015');
clickModel(fbsgf4, meshes[i], '分布式光伏', 6);
let fbsgf5 = meshes[i].id.indexOf('平面.016');
clickModel(fbsgf5, meshes[i], '分布式光伏', 6);
let fbsgf6 = meshes[i].id.indexOf('平面.017');
clickModel(fbsgf6, meshes[i], '分布式光伏', 6);
let fbsgf7 = meshes[i].id.indexOf('平面.019');
clickModel(fbsgf7, meshes[i], '分布式光伏', 6);
let fbsgf8 = meshes[i].id.indexOf('平面.020');
clickModel(fbsgf8, meshes[i], '分布式光伏', 6);
let fbsgf9 = meshes[i].id.indexOf('平面.021');
clickModel(fbsgf9, meshes[i], '分布式光伏', 6);
let fbsgf10 = meshes[i].id.indexOf('平面.029');
clickModel(fbsgf10, meshes[i], '分布式光伏', 6);
let fbsgf11 = meshes[i].id.indexOf('平面.030');
clickModel(fbsgf11, meshes[i], '分布式光伏', 6);
let fbsgf12 = meshes[i].id.indexOf('平面.031');
clickModel(fbsgf12, meshes[i], '分布式光伏', 6);
}
})
return scene;
};
// New Scene
var scene = createScene();
// Looper rendering
engine.runRenderLoop(function () {
scene.render();
});
}, [])
return (
<div
style={{
width: 1920,
height: 1080,
background: '#000',
position: 'relative'
}}>
{/* header */}
<div
style={{
height: 103,
width: '100%',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundImage: `url(${Images.header})`,
position: 'absolute',
top: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between'
}}>
{/* left */}
<div
style={{
display: 'flex',
alignItems: 'center'
}}>
<div
style={{
width: 136,
height: 42,
border: '2px solid #BCE0FF',
borderRadius: 21,
fontSize: 24,
fontWeight: '600',
color: '#FFF',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginLeft: 48,
background: 'rgba(188, 224, 255, 0.07)'
}}>
能源
</div>
<div
style={{
fontSize: 30,
color: '#FFF',
marginLeft: 30,
fontWeight: '800'
}}>
江北能源站
</div>
</div>
{/* right */}
<div
style={{
display: 'flex',
alignItems: 'center'
}}>
<div
style={{
fontSize: 20,
color: '#FFF',
fontWeight: '600'
}}>
{date}
</div>
<div
style={{
fontSize: 20,
color: '#FFF',
fontWeight: '600',
marginLeft: 33,
marginRight: 38
}}>
{week}
</div>
<div
style={{
fontSize: 20,
color: '#FFF',
fontWeight: '600',
marginRight: 38
}}>
{time}
</div>
</div>
</div>
{/* model */}
<div
style={{
width: '100%',
height: 1080
}}>
<canvas
id='cvs'
width={1920}
height={1080}>
</canvas>
{/* content left */}
<div
id='left'
style={{
overflow: 'hidden',
display: 'none',
position: 'absolute',
top: 127,
left: 32,
width: 416, height: 895,
background: 'linear-gradient(180deg, #080F14 0%, #010407 100%)',
opacity: 0.8,
color: '#fff',
alignItems: 'center',
flexDirection: 'column'
}}>
<div
onClick={() => {
let rightContent = document.getElementById('right');
let leftContent = document.getElementById('left');
// tweenjs
var coords = { x: 416, y: 895 };
var tween = new TWEEN.Tween(coords)
.to({ x: 0, y: 0 }, 1000)
.easing(TWEEN.Easing.Quadratic.Out)
.onUpdate(function () {
leftContent.style.setProperty('width', coords.x 'px');
rightContent.style.setProperty('width', coords.x 'px');
})
.start();
animate();
function animate() {
requestAnimationFrame(animate);
TWEEN.update();
}
}}
style={{
cursor: 'pointer',
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
marginTop: 8,
width: 400,
height: 36,
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundImage: `url(${Images.bt})`
}}>
<span style={{ marginLeft: 56, fontSize: 18 }}>{currentTitle}</span>
</div>
</div>
{/* content right */}
<div
id='right'
style={{
overflow: 'hidden',
display: 'none',
position: 'absolute',
top: 127,
right: 32,
width: 416,
height: 895,
background: 'linear-gradient(180deg, #080F14 0%, #010407 100%)',
opacity: 0.8
}}>
<span
onClick={() => {
navigate('/details')
}}
style={{ color: '#fff', cursor: 'pointer', marginTop: 8, marginLeft: 8 }}>
详情
</span>
</div>
</div>
{/* footer */}
<div
style={{
height: 18,
width: '100%',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundImage: `url(${Images.footer})`,
position: 'absolute',
bottom: 13
}}>
</div>
</div>
)
}
export default Home
视频效果
示例视频
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfgjhc
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13