three.js場景的背景旋轉主體不動

方法一 創建兩個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)

爲什麼呢?我不知道瞎蒙的試了幾次中了,求解…………

效果截圖

明顯能看出背景在轉動,而主體部分(藍色線)保持不動。
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章