Web应用之数据大屏
一、技术栈
- React 17.0.0 搭建脚手架
- Eahcrt常规图表
- Svga动画
- 3D模型-Three.Js
- 大屏适配-目标大屏(4K -3840*2160)
二、React 17.0.0 脚手架搭建
npx create-react-app my-app
cd my-app
npm start
具体详细情况,自行官网查看React官网
三、Echarts常规图表
1、echarts-for-react Echarts的React版本
$ npm install --save echarts-for-react
# `echarts` is the peerDependence of `echarts-for-react`, you can install echarts with your own version.
$ npm install --save echarts
import ReactECharts from 'echarts-for-react';
// render echarts option.
<ReactECharts option={this.getOption()} />
四、Svga动画
1、svga动画支持IOS、安卓、Web
2、官网网站:详细使用
3、Web使用方式:
直接在:https://github.com/svga/SVGAPlayer-Web下载 build/svga.min.js,
并添加至目标页面。
或使用 npm install svgaplayerweb —save 添加依赖,
并在需要使用的 js 中添加 require(‘svgaplayerweb’) 添加 Div 容器,并加载动画,
具体方法参见:https://github.com/svga/SVGAPlayer-Web。
我们还提供了体积更小的轻量版:SVGA.Lite
4、代码实列
Add Div Tag.
<div id="demoCanvas" style="styles..."></div>
Load Animation
var player = new SVGA.Player('#demoCanvas');
var parser = new SVGA.Parser('#demoCanvas'); // Must Provide same selector eg:#demoCanvas IF support IE6+
parser.load('rose_2.0.0.svga', function(videoItem) {
player.setVideoItem(videoItem);
player.startAnimation();
})
5、关注点:parse.load的svga文件,最好是网络地址或是将文件放置在服务器地址,使用服务器文件地址引用
5、如果地址存在跨域问题,需要在前端配置代理,具体配置代理,请问度娘。
6、如果配置代理,在parse.load的文件地址是有讲究的,举例如下
(1) 代理的字段:‘/devApi’
(2) 文件地址不代理:https:///images/02top.svga
(3) 文件地址代理:https:///devApi/images/02top.svga
(4) 代码如下:
//不代理 不需要完整的文件地址
parser.load('images/02top.svga', function(videoItem) {
player.setVideoItem(videoItem);
player.startAnimation();
})
//代理 不需要完整的文件地址
parser.load('devApi/images/02top.svga', function(videoItem) {
player.setVideoItem(videoItem);
player.startAnimation();
})
7、如果存在多个svga的动画需要加载,可以尝试数组循环调用
五、3D模型-Three.Js
1、three.js install
npm i three --save
import * as THREE from 'three';
2、如果导入模型,需要准备好glb或者gltf格式的模型文件
3、如果不导入就需要,按照three.js 从几何体 材质 场景 相机 一点点 建立自己的3D模型了,很艰辛的
4、至于three.js 的原理:相机,场景,渲染器的基础,请官网,或者百度自行查看,我直接上代码,有详细注释,也算自己给自己的总结:
import React, { Component } from 'react'
//引入three
import * as THREE from 'three'
//导入控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
//对场景环境做处理
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js'
//模型导入器
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
//用于解码用KHR_draco_mesh_compression扩展名压缩的资产 暂时没看到使用效果
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
//对模型进行后期处理 处理辉光 轨迹 等特殊效果
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
//处理增加后期效果 的 辉光后,场景出现
import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
// import { SSAARenderPass } from 'three/examples/jsm/postprocessing/SSAARenderPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js'
import * as dat from 'dat.gui'
import gsap from 'gsap'
class B3Model extends Component {
constructor(props) {
super(props)
this.state = {
commonModel: null,
}
//性能控制器,显示当前模型的性能数据
// const stats = new Stats()
//3d模型导入工具
const fltfLoader = new GLTFLoader()
//一个几何图形的加载器,用德拉科库压缩。
const dracoLoader = new DRACOLoader()
//该对象用于跟踪时间。如果performance.now可用,则 Clock 对象通过该方法实现,否则回落到使用略欠精准的Date.now来实现。
const clock = new THREE.Clock()
let mixer
//渲染的容器
this.container = null;
//渲染器
this.renderer = null;
this.pmremGenerator = null;
this.scene = null
this.camera = null
this.controls = null
this.composer = null
this.outLinePass = null
this.effectFXAA = null
this.mouse = null
this.rayCaster = null
this.ssaaRenderPass = null
this.initTime = new Date();//上次时间
this.initNumber = 1;
this.rendererer = () => {
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
this.container = document.getElementById('b3Screen');
//Window 接口的devicePixelRatio返回当前显示设备的物理像素分辨率
// 与CSS像素分辨率之比。 此值也可以解释为像素大小的比率:一个CSS像素
// 的大小与一个物理像素的大小。 简单来说,它告诉浏览器应使用多少屏幕
// 实际像素来绘制单个CSS像素。
this.renderer.setPixelRatio(window.devicePixelRatio)
//渲染器设置尺寸
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight)
//定义呈现程序的输出编码。默认是THREE.LinearEncoding。
this.renderer.outputEncoding = THREE.sRGBEncoding
this.renderer.shadowMap.enabled = true
this.renderer.physicallyCorrectLights = true
//渲染器放置到实际的dom上面
this.container.appendChild(this.renderer.domElement)
this.pmremGenerator = new THREE.PMREMGenerator(this.renderer)
}
//场景
this.scener = () => {
this.scene = new THREE.Scene()
// 创建一个纹理图片加载器加载图片
// var textureLoader = new THREE.TextureLoader();
// var texture = textureLoader.load('b3Image/background.png');
// 纹理对象Texture赋值给场景对象的背景属性.background
// scene.background = texture
//场景的背景颜色
this.scene.background = new THREE.Color("rgb(0, 0, 0)")
//理论想加一个光源
// const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// directionalLight.position.set(15, 10, 0);
// this.scene.add(directionalLight);
this.scene.environment = this.pmremGenerator.fromScene(
new RoomEnvironment(),
0.04
).texture
// const axesHelper = new THREE.AxesHelper(5);
// this.scene.add(axesHelper);
}
//设置相机
this.camerer = () => {
this.camera = new THREE.PerspectiveCamera(
60,
window.innerWidth / window.innerHeight,
0.1,
1000
)
this.camera.position.set(0, 2, -2)
}
//控制器
this.controlser = () => {
let THAT = this;
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
this.controls.target.set(0, .5, 0)
// 更新控制。必须在任何手动改变相机变换后调用,或者在更新循环中,如果设置了. autorotate或. enabledamping。
this.controls.update()
this.controls.enabled = false
// 启用或禁用摄像机平移。默认是正确的。
this.controls.enablePan = true
// 设置为true使能阻尼(惯性),可以用来给控制的重量感。默认是假的。
// 注意,如果启用了此功能,则必须在动画循环中调用.update()。
this.controls.enableDamping = true
// 视角最小距离
// this.controls.minDistance = 1;
// 视角最远距离
// this.controls.maxDistance = 5000;
this.controls.dampingFactor = 0.5;
//设置模型垂直旋转的最大和最小角度
this.controls.minPolarAngle = 0;
this.controls.maxPolarAngle = Math.PI / 2.7;
}
//模型加载
this.moduleLoader = () => {
let THAT = this;
//模型文件和模型输出格式文件都放置在public
// dracoLoader.setDecoderPath('js/libs/draco/gltf/')
//用于解码用KHR_draco_mesh_compression扩展名压缩的资产。
// fltfLoader.setDRACOLoader(dracoLoader)
// 'models/gltf/LittlestTokyo.glb'
fltfLoader.load(
'models/glb/B30215.glb',
function (gltf) {
//获取到整体模型的场景
const model = gltf.scene
//改变模型子模型的属性
//需要判断没个子模型具有的数据 然后给模型添加上去
model.children = model.children.filter(item => item.name !== "camera")
let modelChildrenArray = [];
model.children.forEach(item => {
//1、判断是否是mesh
if (item.isMesh) {
//改变部分模型的透明度
item.material.shininess = 1;
item.castShadow = true
item.receiveShadow = true
item.material.transparent = true
if (item.name === 'building02' || item.name === 'building03' || item.name === 'building03') {
//修改模型透明 需要修改此属性为false 否则会造成底部马赛克问题
item.material.depthTest = false;
item.material.opacity = 0.2
}
if (item.name === "b3") {
//关闭b3的透明度
item.material.transparent = false
}
//修改蓝色组件的颜色
if (item.name === 'plate07') {
//此材质 有发光属性 发光强度过高 导致太亮了 修改发光强度
item.material.emissiveIntensity = 1
}
}
//找到底部地面 把地面的材质修改为不改光材质
if (item.name === 'ground') {
item.material = new THREE.MeshBasicMaterial({ color: item.material.color })
}
//对组件感光处理
modelChildrenArray.push(item)
})
//初始位置
// model.position.set(-0.65, 0.97, -0.38)
model.scale.set(0.03, 0.03, 0.03)
gsap.to(model.position, {
x: -0.65,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.position, {
y: 0.97,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.position, {
z: -0.38,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.rotation, {
x: 0,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.rotation, {
y: Math.PI / 1.7224,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.rotation, {
z: Math.PI / 14.40367,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.scale, {
x: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.scale, {
y: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(model.scale, {
z: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
// model.scale.set(0.015, 0.015, 0.015)
// model.rotation.x = 0
// model.rotation.y = Math.PI / 1.7224
// model.rotation.z = Math.PI / 14.40367
THAT.setState({
commonModel: model
}, () => {
// console.log(THAT.state.commonModel)
THAT.scene.add(THAT.state.commonModel)
THAT.animate(THAT.state.commonModel)
THAT.setState({
loading: false
}, () => {
// THAT.initLocation()
})
})
},
undefined,
function (e) {
console.error(e)
}
)
}
//后期处理 outLine效果
this.initBloom = () => {
//将效果和渲染器合并
//选中物体的插件 光线捕捉器
this.rayCaster = new THREE.Raycaster()
//选中的原理是鼠标从我们看向的正面发出一束光线 穿过几个物体就把物体放在一个数据
this.mouse = new THREE.Vector2()
//使用renderTarget 渲染composer
const pixelRatio = this.renderer.getPixelRatio();
var renderTarget = new THREE.WebGLRenderTarget(
this.container.clientWidth * pixelRatio,
this.container.clientHeight * pixelRatio,
{
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBAFormat,
stencilBuffer: false,
type: THREE.FloatType,
}
);
renderTarget.texture.name = "EffectComposer.rt1";
this.composer = new EffectComposer(this.renderer);
//对composer的进一步处理
this.composer.setPixelRatio(window.devicePixelRatio);
this.composer.setSize(this.container.clientWidth, this.container.clientHeight);
let renderPass = new RenderPass(this.scene, this.camera);
this.composer.addPass(renderPass)
//处理条带
// this.ssaaRenderPass = new SSAARenderPass(this.scene, this.camera);
// this.composer.addPass(this.ssaaRenderPass)
//处理背景变暗
let effectColorSpaceConversion = new ShaderPass(GammaCorrectionShader)
this.composer.addPass(effectColorSpaceConversion)
//轮廓线
this.outLinePass = new OutlinePass(new THREE.Vector2(this.container.clientWidth, this.container.clientHeight), this.scene, this.camera)
//轮廓线 配置
const params = {
edgeStrength: 5.0,
edgeGlow: 2.0,
edgeThickness: 1.0,
pulsePeriod: 3.5,
rotate: false,
usePatternTexture: false
};
this.outLinePass.edgeStrength = params.edgeStrength;//包围线浓度
this.outLinePass.edgeGlow = params.edgeGlow;//边缘线范围
this.outLinePass.edgeThickness = params.edgeThickness;//边缘线浓度
this.outLinePass.pulsePeriod = params.pulsePeriod;;//包围线闪烁频率
this.outLinePass.visibleEdgeColor.set('#8DDBFF');//包围线颜色
this.outLinePass.hiddenEdgeColor.set('#8DDBFF');//被遮挡的边界线颜色
this.composer.addPass(this.outLinePass)
//处理锯齿
this.effectFXAA = new ShaderPass(FXAAShader);
this.effectFXAA.uniforms["resolution"].value.set(
1 / this.container.clientWidth,
1 / this.container.clientHeight
)
this.effectFXAA.renderToScreen = true;
// 解决 增加 边缘线闪烁 后场景变暗的问题
this.composer.addPass(this.effectFXAA)
}
this.resizeRendererToDisplaySize = (renderer) => {
if (renderer) {
const { width, height, clientWidth, clientHeight } = renderer.domElement;
const needResize = width !== clientWidth || height !== clientHeight;
if (needResize) {
renderer.setSize(clientWidth, clientHeight, false);
}
return needResize;
}
}
this.animate = (model) => {
let THAT = this;
let CurrentTime = new Date();//本次时间
let MODEL = THAT.scene.children[0]
// console.log(`${(CurrentTime - THAT.initTime) / 1000 / 60} --- ${THAT.initNumber}`)
if (THAT.initNumber === 1) {
if ((CurrentTime - THAT.initTime) / 1000 / 60 >= 0.5 && THAT.props.animateFlag) {
THAT.outLinePass.selectedObjects = []
console.log(THAT.initNumber + '整数分钟了')
this.props.changeModelLocation('facade')
THAT.initNumber = THAT.initNumber + 1;
//到南立面
// MODEL.position.set(-2.26, -0.38, 4.46)
// MODEL.scale.set(0.06, 0.06, 0.06)
// MODEL.rotation.x = 0
// MODEL.rotation.y = Math.PI / 1.8
// MODEL.rotation.z = - Math.PI / 92
//使用gsap动画
gsap.to(MODEL.position, {
x: -2.26,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: -0.38,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: 4.46,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: 0,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 1.8,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: - Math.PI / 92,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
if (MODEL.children.length > 0) {
MODEL.children.forEach(item => {
if (item.name === 'plate07') {
THAT.outLinePass.selectedObjects = [item]
}
if (item.name === 'plate09') {
THAT.outLinePass.selectedObjects.push(item)
}
})
}
}
} else {
if ((CurrentTime - THAT.initTime) / 1000 / 60 >= THAT.initNumber * 0.5 && THAT.props.animateFlag) {
console.log(THAT.initNumber + '整数分钟了')
//南立面
if ((THAT.initNumber - 1) % 4 === 0) {
THAT.outLinePass.selectedObjects = []
THAT.props.changeModelLocation('facade')
gsap.to(MODEL.position, {
x: -2.26,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: -0.38,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: 4.46,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: 0,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 1.8,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: - Math.PI / 92,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
if (MODEL.children.length > 0) {
MODEL.children.forEach(item => {
if (item.name === 'plate07') {
THAT.outLinePass.selectedObjects = [item]
}
if (item.name === 'plate09') {
THAT.outLinePass.selectedObjects.push(item)
}
})
}
}
//屋顶
if ((THAT.initNumber - 2) % 4 === 0 || THAT.initNumber === 2) {
THAT.outLinePass.selectedObjects = []
this.props.changeModelLocation('roof')
//隆顶位置01
//设置模型的位置 设置模型的放大的比例 设置模型初始化角度
gsap.to(MODEL.position, {
x: -1.45,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: -1.18,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: -0.915,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: - Math.PI / 10.94,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 2,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: - Math.PI / 10.94,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.033,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.033,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.033,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
// MODEL.position.set(-1.45, -1.18, -0.915)
// MODEL.scale.set(0.033, 0.033, 0.033)
// MODEL.rotation.x = - Math.PI / 10.94
// MODEL.rotation.y = Math.PI / 2
// MODEL.rotation.z = - Math.PI / 10.94
if (MODEL.children.length > 0) {
MODEL.children.forEach(item => {
if (item.name === 'plate01') {
THAT.outLinePass.selectedObjects = [item]
}
})
}
}
//阳光房
if ((THAT.initNumber - 3) % 4 === 0 || THAT.initNumber === 3) {
THAT.outLinePass.selectedObjects = []
this.props.changeModelLocation('sun')
//阳光房 02
gsap.to(MODEL.position, {
x: -3.33,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: -1.18,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: 0.16,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: 0,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 1.21654,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: 0,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.06,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.06,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.06,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
// MODEL.position.set(-3.33, -1.18, 0.16)
// MODEL.scale.set(0.06, 0.06, 0.06)
// MODEL.rotation.x = 0
// MODEL.rotation.y = Math.PI / 1.21654
// MODEL.rotation.z = 0
if (MODEL.children.length > 0) {
MODEL.children.forEach(item => {
if (item.name === 'plate06') {
THAT.outLinePass.selectedObjects = [item]
}
})
}
}
//整体
if ((THAT.initNumber - 4) % 4 === 0 || THAT.initNumber === 4) {
THAT.outLinePass.selectedObjects = []
this.props.changeModelLocation('all')
gsap.to(MODEL.position, {
x: -0.65,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: 0.97,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: -0.38,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: 0,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 1.7224,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: Math.PI / 14.40367,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
}
THAT.initNumber = THAT.initNumber + 1;
}
}
mixer = new THREE.AnimationMixer(model)
const delta = clock.getDelta()
mixer.update(delta)
if (this.resizeRendererToDisplaySize(THAT.renderer)) {
const canvas = THAT.renderer.domElement;
THAT.camera.aspect = canvas.clientWidth / canvas.clientHeight;
THAT.camera.updateProjectionMatrix();
THAT.composer.setSize(canvas.width, canvas.height);
}
// THAT.renderer.render(THAT.scene, THAT.camera)
THAT.composer.render(delta)
THAT.controls.update()
requestAnimationFrame(this.animate)
}
//手动出发模型动画
this.mateChangeModelLocation = (type) => {
let THAT = this;
let MODEL = THAT.scene.children[0]
if (type === 'all') {
THAT.outLinePass.selectedObjects = []
this.props.changeModelLocation('all')
gsap.to(MODEL.position, {
x: -0.65,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: 0.97,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: -0.38,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: 0,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 1.7224,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: Math.PI / 14.40367,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.015,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
} else if (type === 'facade') {
THAT.outLinePass.selectedObjects = []
THAT.props.changeModelLocation('facade')
gsap.to(MODEL.position, {
x: -2.26,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: -0.38,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: 4.46,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: 0,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 1.8,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: - Math.PI / 92,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.06,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
if (MODEL.children.length > 0) {
MODEL.children.forEach(item => {
if (item.name === 'plate07') {
THAT.outLinePass.selectedObjects = [item]
}
if (item.name === 'plate09') {
THAT.outLinePass.selectedObjects.push(item)
}
})
}
} else if (type === 'roof') {
THAT.outLinePass.selectedObjects = []
this.props.changeModelLocation('roof')
//隆顶位置01
//设置模型的位置 设置模型的放大的比例 设置模型初始化角度
gsap.to(MODEL.position, {
x: -1.45,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: -1.18,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: -0.915,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: - Math.PI / 10.94,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 2,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: - Math.PI / 10.94,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.033,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.033,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.033,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
// MODEL.position.set(-1.45, -1.18, -0.915)
// MODEL.scale.set(0.033, 0.033, 0.033)
// MODEL.rotation.x = - Math.PI / 10.94
// MODEL.rotation.y = Math.PI / 2
// MODEL.rotation.z = - Math.PI / 10.94
if (MODEL.children.length > 0) {
MODEL.children.forEach(item => {
if (item.name === 'plate01') {
THAT.outLinePass.selectedObjects = [item]
}
})
}
} else if (type === 'sun') {
THAT.outLinePass.selectedObjects = []
this.props.changeModelLocation('sun')
//阳光房 02
gsap.to(MODEL.position, {
x: -3.33,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
y: -1.18,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.position, {
z: 0.16,
duration: 5,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
x: 0,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
y: Math.PI / 1.21654,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.rotation, {
z: 0,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
x: 0.06,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
y: 0.06,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
gsap.to(MODEL.scale, {
z: 0.06,
duration: 3,
ease: 'power1.inOut',
yoyo: true
})
// MODEL.position.set(-3.33, -1.18, 0.16)
// MODEL.scale.set(0.06, 0.06, 0.06)
// MODEL.rotation.x = 0
// MODEL.rotation.y = Math.PI / 1.21654
// MODEL.rotation.z = 0
if (MODEL.children.length > 0) {
MODEL.children.forEach(item => {
if (item.name === 'plate06') {
THAT.outLinePass.selectedObjects = [item]
}
})
}
}
}
this.pageClick = (e) => {
let THAT = this
let x, y
x = e.clientX
y = e.clientY
THAT.mouse.x = (x / THAT.container.clientWidth) * 2 - 1
THAT.mouse.y = -(y / THAT.container.clientHeight) * 2 + 1
THAT.rayCaster.setFromCamera(THAT.mouse, THAT.camera)
let intersects = THAT.rayCaster.intersectObjects([THAT.scene], true)
if (intersects.length > 0) {
THAT.outLinePass.selectedObjects = [intersects[0].object]
}
}
//获取当前模型的位置
this.initLocation = () => {
let THAT = this;
const gui = new dat.GUI({
width: 200
})
// const f = gui.addFolder('B3模型控制器');
//设置最大值max 最小值min 步调step 名字name 改变的回调
//控制x y z
gui.add(THAT.scene.position, 'x').min(-10).max(10).step(0.01).name('positionX').onFinishChange((value) => {
console.log(value)
});
gui.add(THAT.scene.position, 'y').min(-10).max(10).step(0.01).name('positionY').onFinishChange((value) => {
console.log(value)
});
gui.add(THAT.scene.position, 'z').min(-10).max(10).step(0.005).name('positionZ').onFinishChange((value) => {
console.log(value)
});
//控制旋转
gui.add(THAT.scene.rotation, 'x').min(-Math.PI).max(Math.PI).step(Math.PI / 180 / 2).name('rotationX').onFinishChange((value) => {
console.log(value)
});
gui.add(THAT.scene.rotation, 'y').min(-Math.PI).max(Math.PI).step(Math.PI / 180 / 2).name('rotationY').onFinishChange((value) => {
console.log(value)
});
gui.add(THAT.scene.rotation, 'z').min(-Math.PI).max(Math.PI).step(Math.PI / 180 / 2).name('rotationZ').onFinishChange((value) => {
console.log(value)
});
//控制放到缩小
gui.add(THAT.scene.children[0].scale, 'x').min(0).max(10).step(0.0001).name('modelpositionX').onFinishChange((value) => {
console.log(value)
THAT.scene.children[0].scale.set(value, value, value)
});
}
this.init = () => {
let THAT = this;
THAT.rendererer();
THAT.scener();
THAT.camerer();
THAT.controlser();
THAT.initBloom();
THAT.moduleLoader();
window.onresize = function () {
THAT.camera.aspect = THAT.container.clientWidth / THAT.container.clientHeight
THAT.camera.updateProjectionMatrix()
//renderer 根据尺寸重绘
THAT.renderer.setSize(THAT.container.clientWidth, THAT.container.clientHeight)
//后期处理 根据尺寸重绘
THAT.composer.setSize(THAT.container.clientWidth, THAT.container.clientHeight)
//使用着色解决锯齿
THAT.effectFXAA.uniforms["resolution"].value.set(
1 / THAT.container.clientWidth,
1 / THAT.container.clientHeight
)
}
}
}
componentDidMount() {
this.init();
}
render() {
return (
<div className='b3-screen-content' id="b3Screen">
</div>
)
}
}
export default B3Model