欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

three.js场景的背景旋转主体不动

程序员文章站 2022-05-26 18:28:56
...

方法一 创建两个THREE对象分层控制

两个DIV,创建两个THREE对象,完全弄出两套

<div id="divBG"></div>
<div id="divZT"></div>

divBG,绑定创建THREE对象1,在场景中添加背景图片,设置controls的自动旋转,关键代码如下:

initScene () {
  // 场景作为一个容器
  scene = new THREE.Scene()
  let urls = ['dark-s_px.jpg', 'dark-s_nx.jpg', 'dark-s_py.jpg', 'dark-s_ny.jpg', 'dark-s_pz.jpg', 'dark-s_nz.jpg']
  let loader = new THREE.CubeTextureLoader()
  loader.setPath('/static/three/MilkyWay/')
  let background = loader.load(urls)
  scene.background = background
},
initControls () {
  controls = new OrbitControls(camera, renderer.domElement)
  controls.autoRotate = true // 是否自动旋转
  controls.autoRotateSpeed = 1.0 // 自动旋转的速度,默认值是 2.0,即渲染满60帧的情况下30秒旋转360度。
},

注意camera、renderer等绑定的是divBG对应的dom。
divZT,绑定创建THREE对象2,场景不要设置背景,直接加载主体不需要转动的部分。
在此不赘述,重点在方法二。

方法二 场景旋转主体逆向旋转

全部绑定在一个DIV上实现,创建一个THREE对象,给其最外层场景设置背景,同时设置controls.autoRotate的自动旋转。此时,整个场景里的对象都会旋转起来,为了让主体部分保持不动,只需设置主体部分进行逆向旋转即可。
关键步骤如下:

1、创建DIV

<div id="divOne"></div>
divOne = document.getElementById('divOne')

2、创建外层场景并添加背景图片,创建子场景放置不旋转的对象

// 场景
initScene () {
  scene = new THREE.Scene()
  // 给当前场景容器添加背景图片
  let urls = ['dark-s_px.jpg', 'dark-s_nx.jpg', 'dark-s_py.jpg', 'dark-s_ny.jpg', 'dark-s_pz.jpg', 'dark-s_nz.jpg']
  let loader = new THREE.CubeTextureLoader()
  loader.setPath('/static/three/MilkyWay/')
  let background = loader.load(urls)
  scene.background = background
  // 创建一个groupNoRotate不随着场景旋转而旋转
  groupNoRotate = new THREE.Group()
  scene.add(groupNoRotate)
},

3、添加灯光至外层场景,跟随背景旋转

// 灯光
initLight () {
  let ambientLight = new THREE.AmbientLight(0xffffff) // 环境光
  let directionalLight = new THREE.DirectionalLight(0xffffff, 0.1) // 平行光
  directionalLight.position.set(5, 10, 5)
  let pointLight = new THREE.PointLight(0xffffff) // 点光源
  pointLight.position.set(30, 10, 10)
  // 将光源加入场景 因为加入scene而不是groupNoRotate 所以光源也会自动转动
  scene.add(ambientLight)
  scene.add(directionalLight)
  scene.add(pointLight)
},

4、设置控制器的自动旋转及自动旋转速度

// 控制器
initControls () {
  controls = new OrbitControls(camera, renderer.domElement)
  ……
  controls.autoRotate = true // 是否自动旋转
  controls.autoRotateSpeed = 1.0 // 自动旋转的速度,默认值是 2.0,即渲染满60帧的情况下30秒旋转360度。
  ……
},

5、加载模型至内层场景groupNoRotate

// 模型加载
initModel () {
  // 实例化加载器
  let loader = new GLTFLoader()
  loader.load('/static/three/model/line.glb', function (obj) {
    if (groupNoRotate !== null) {
      groupNoRotate.add(obj.scene) // 此处需将模型加载到groupNoRotate中一同控制groupNoRotate逆旋转
    }
    console.log('loaded')
  }, function (xhr) {
    console.log(xhr.loaded, 'loading')
  }, function (error) {
    console.error(error, 'load error!')
  })
},

6、场景动画,将内层场景y轴旋转设置为逆向旋转

// 场景动画
animate () {
  // 控制groupNoRotate里面的所有对象一起逆向旋转,场景在自动旋转,所以表现为不旋转
  if (groupNoRotate !== null) {
    groupNoRotate.rotation.y = groupNoRotate.rotation.y - Math.PI / (30 * 60)
  }
  controls.update()
  renderer.render(scene, camera)
  stop = requestAnimationFrame(this.animate)
},

关键点

自动旋转的速度controls.autoRotateSpeed要和逆向旋转的角度groupNoRotate.rotation.y相抵消!!!

controls.autoRotateSpeed = 1.0 // 自动旋转的速度,默认值是 2.0,即渲染满60帧的情况下30秒旋转360度。
groupNoRotate.rotation.y = groupNoRotate.rotation.y - Math.PI / (30 * 60)

经测试发现,groupNoRotate.rotation.y每次的减幅应该是Math.PI / (30 * 60) * autoRotateSpeed。

controls.autoRotateSpeed = k
groupNoRotate.rotation.y = groupNoRotate.rotation.y - Math.PI * k / (30 * 60)

为什么呢?我不知道瞎蒙的试了几次中了,求解…………

效果截图

明显能看出背景在转动,而主体部分(蓝色线)保持不动。
three.js场景的背景旋转主体不动
three.js场景的背景旋转主体不动

相关标签: threejs