threejs

官网:https://threejs.org/

我们先了解几个概念

  • 场景
    • 场景就是一个显示呈现的舞台
  • 相机
    • 浏览器端呈现的内容都是相机拍摄
  • 渲染
    • 渲染器决定了内容如何呈现至屏幕
  • 几何体

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

一、threejs绘制立方体

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>绘制立方体</title>
  <script src="./three.min.js"></script>
</head>

<body>
  <script>
    /**
    01 场景 
    02 相机: 分类 位置
    03 渲染器:大小 颜色
    04 几何体:
    */
    const scene = new THREE.Scene()

	/**
	*fov — 摄像机视锥体垂直视野角度
	aspect — 摄像机视锥体长宽比
	near — 摄像机视锥体近端面
	far — 摄像机视锥体远端面
	*/
    const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000) 

    const renderer = new THREE.WebGLRenderer({
      
      
      antialias: true
    })
    renderer.setClearColor(0xffffff)
    renderer.setSize(window.innerWidth, window.innerHeight)

    document.body.appendChild(renderer.domElement)

    const geometry = new THREE.BoxGeometry(1, 1, 1) // x轴、y轴、z轴
    const material = new THREE.MeshBasicMaterial({
      
       // 材质
      color: 0x285b41,
      wireframe: true // 透明
    })

    const cube = new THREE.Mesh(geometry, material)
    scene.add(cube)
    camera.position.z = 4

    function animate() {
      
      

      requestAnimationFrame(animate)
      cube.rotation.y += 0.01
      cube.rotation.x += 0.01
      renderer.render(scene, camera)
    }

    animate()

  </script>
</body>

</html>

二、材质与相机控制

在这里插入图片描述
anywhere启动html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>轨迹球控制与材质</title>
  <script src="./three.min.js"></script>
  <script src="./TrackballControls.js"></script>
</head>

<body>
  <script>
    // 定义全局变量
    let scene, camera, geometry, mesh, renderer, controls

    // 初始化渲染器
    function initRenderer() {
      
      
      renderer = new THREE.WebGLRenderer({
      
       antialias: true })
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.setPixelRatio(window.devicePixelRatio)
      document.body.appendChild(renderer.domElement)
    }

    // 初始化场景
    function initScene() {
      
      
      scene = new THREE.Scene()
      const axesHelper = new THREE.AxesHelper(100)
      scene.add(axesHelper)
    }

    // 初始化相机
    function initCamera() {
      
      
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
      camera.position.set(0, 0, 15)
      controls = new THREE.TrackballControls(camera, renderer.domElement)
    }

    // 初始化模型
    function initMesh() {
      
      
      geometry = new THREE.BoxGeometry(2, 2, 2)
      // material = new THREE.MeshNormalMaterial()
      const texture = new THREE.TextureLoader().load('img/crate.gif')
      material = new THREE.MeshBasicMaterial({
      
      
        map: texture,
        side: THREE.DoubleSide
      })
      mesh = new THREE.Mesh(geometry, material)
      scene.add(mesh)
    }

    // 初始化动画
    function animate() {
      
      
      requestAnimationFrame(animate)
      controls.update()
      renderer.render(scene, camera)
    }

    // 定义初始化方法
    function init() {
      
      
      initRenderer()
      initScene()
      initCamera()
      initMesh()
      animate()
    }

    init()

  </script>
</body>

</html>

三、光源操作

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>设置场景光</title>
  <script src="./three.min.js"></script>
  <script src="./TrackballControls.js"></script>
</head>

<body>
  <script>
    // 定义全局变量
    let scene, camera, geometry, mesh, renderer, controls

    // 初始化渲染器
    function initRenderer() {
      
      
      renderer = new THREE.WebGLRenderer({
      
       antialias: true })
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.setPixelRatio(window.devicePixelRatio)
      document.body.appendChild(renderer.domElement)
    }

    // 初始化场景
    function initScene() {
      
      
      scene = new THREE.Scene()
      const axesHelper = new THREE.AxesHelper(100)
      scene.add(axesHelper)

      //添加光源

      // const directionalLight = new THREE.DirectionalLight('red') // 平行光

      // const ambientLight = new THREE.AmbientLight('orange') // 全局环境光

      // const pointLight = new THREE.PointLight('green') // 点光源

      // const spotLight = new THREE.SpotLight('lightblue') // 聚光灯

      const hemisphereLight = new THREE.HemisphereLight('red') // 半球光

      hemisphereLight.position.set(0, 30, 0)
      scene.add(hemisphereLight)

    }

    // 初始化相机
    function initCamera() {
      
      
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
      camera.position.set(0, 0, 15)
      controls = new THREE.TrackballControls(camera, renderer.domElement)
    }

    // 初始化模型
    function initMesh() {
      
      
      geometry = new THREE.SphereGeometry(3, 26, 26)
      const texture = new THREE.TextureLoader().load('img/crate.gif')
      material = new THREE.MeshPhongMaterial({
      
      
        map: texture,
        side: THREE.DoubleSide
      })
      mesh = new THREE.Mesh(geometry, material)
      scene.add(mesh)
    }

    // 初始化动画
    function animate() {
      
      
      requestAnimationFrame(animate)
      controls.update()
      renderer.render(scene, camera)
    }

    // 定义初始化方法
    function init() {
      
      
      initRenderer()
      initScene()
      initCamera()
      initMesh()
      animate()
    }

    init()

  </script>
</body>

</html>

四、精灵材质及交互

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>精灵材质与3D交互</title>
  <style>
    * {
      
      
      margin: 0;
      padding: 0;
    }

    canvas {
      
      
      width: 100%;
      height: 100%;
      display: block;
    }
  </style>
  <script src="./three.min.js"></script>
  <script src="./TrackballControls.js"></script>
</head>

<body>
  <script>
    // 定义全局变量
    let scene, camera, geometry, mesh, renderer, controls

    const raycaster = new THREE.Raycaster()
    const mouse = new THREE.Vector2()

    function onMouseMove(event) {
      
      

      // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)

      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;

    }

    window.addEventListener('mousemove', onMouseMove, false)

    window.addEventListener('click', function () {
      
      
      // 计算物体和射线的焦点
      const intersects = raycaster.intersectObjects([mesh])
      if (intersects.length > 0) {
      
      
        mesh.rotation.x += 01
      }
    }, false)


    // 初始化渲染器
    function initRenderer() {
      
      
      renderer = new THREE.WebGLRenderer({
      
       antialias: true })
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.setPixelRatio(window.devicePixelRatio)
      document.body.appendChild(renderer.domElement)
    }

    // 初始化场景
    function initScene() {
      
      
      scene = new THREE.Scene()
      const axesHelper = new THREE.AxesHelper(100)
      scene.add(axesHelper)
    }

    // 初始化相机
    function initCamera() {
      
      
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
      camera.position.set(0, 0, 15)
      controls = new THREE.TrackballControls(camera, renderer.domElement)
    }

    // 初始化模型
    function initMesh() {
      
      

      // const map = new THREE.TextureLoader().load('img/icon.png')
      // const material = new THREE.SpriteMaterial({ map: map, color: 0xffffff })
      // const sprite = new THREE.Sprite(material)
      // scene.add(sprite)

      geometry = new THREE.BoxGeometry(2, 2, 2)
      // material = new THREE.MeshNormalMaterial()
      const texture = new THREE.TextureLoader().load('img/crate.gif')
      material = new THREE.MeshBasicMaterial({
      
      
        map: texture,
        side: THREE.DoubleSide
      })
      mesh = new THREE.Mesh(geometry, material)
      scene.add(mesh)
    }

    // 初始化动画
    function animate() {
      
      
      requestAnimationFrame(animate)
      controls.update()
      renderer.render(scene, camera)
    }

    // 定义初始化方法
    function init() {
      
      
      initRenderer()
      initScene()
      initCamera()
      initMesh()
      animate()
    }

    init()

  </script>
</body>

</html>

五、VR全景拼装

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>轨迹球控制与材质</title>
  <style>
    * {
      
      
      margin: 0;
      padding: 0;
    }

    canvas {
      
      
      display: block;
      height: 100%;
      width: 100%;
    }
  </style>
  <script src="./three.min.js"></script>
  <script src="./TrackballControls.js"></script>
</head>

<body>
  <script>
    // 定义全局变量
    let scene, camera, geometry, mesh, renderer, controls

    // 初始化渲染器
    function initRenderer() {
      
      
      renderer = new THREE.WebGLRenderer({
      
       antialias: true })
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.setPixelRatio(window.devicePixelRatio)
      document.body.appendChild(renderer.domElement)
    }

    // 初始化场景
    function initScene() {
      
      
      scene = new THREE.Scene()
      const axesHelper = new THREE.AxesHelper(100)
      scene.add(axesHelper)
    }

    // 初始化相机
    function initCamera() {
      
      
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
      camera.position.set(0, 0, 15)
      controls = new THREE.TrackballControls(camera, renderer.domElement)
    }

    // 初始化模型
    function initMesh() {
      
      

      // 前面
      const geometryF = new THREE.PlaneGeometry(4, 4)
      const materialF = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/0_f.jpg'),
        side: THREE.DoubleSide
      })
      const meshF = new THREE.Mesh(geometryF, materialF)
      meshF.rotation.y = 180 * Math.PI / 180
      meshF.position.z = 2
      scene.add(meshF)

      // 后面
      const geometryB = new THREE.PlaneGeometry(4, 4)
      const materialB = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/0_b.jpg'),
        side: THREE.DoubleSide
      })
      const meshB = new THREE.Mesh(geometryB, materialB)
      // meshB.rotation.y = 180 * Math.PI / 180
      meshB.position.z = -2
      scene.add(meshB)

      // 左侧 
      const geometryL = new THREE.PlaneGeometry(4, 4)
      const materialL = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/0_l.jpg'),
        side: THREE.DoubleSide
      })
      const meshL = new THREE.Mesh(geometryL, materialL)
      meshL.rotation.y = (-90) * Math.PI / 180
      meshL.position.x = 2
      scene.add(meshL)

      // 右侧 
      const geometryR = new THREE.PlaneGeometry(4, 4)
      const materialR = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/0_r.jpg'),
        side: THREE.DoubleSide
      })
      const meshR = new THREE.Mesh(geometryR, materialR)
      meshR.rotation.y = (90) * Math.PI / 180
      meshR.position.x = -2
      scene.add(meshR)

      // 上面
      const geometryU = new THREE.PlaneGeometry(4, 4)
      const materialU = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/0_u.jpg'),
        side: THREE.DoubleSide
      })
      const meshU = new THREE.Mesh(geometryU, materialU)
      meshU.rotation.x = (90) * Math.PI / 180
      meshU.rotation.z = (180) * Math.PI / 180
      meshU.position.y = 2
      scene.add(meshU)

      // 下面
      const geometryD = new THREE.PlaneGeometry(4, 4)
      const materialD = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/0_d.jpg'),
        side: THREE.DoubleSide
      })
      const meshD = new THREE.Mesh(geometryD, materialD)
      meshD.rotation.x = (-90) * Math.PI / 180
      meshD.rotation.z = (180) * Math.PI / 180
      meshD.position.y = -2
      scene.add(meshD)
    }

    // 初始化动画
    function animate() {
      
      
      requestAnimationFrame(animate)
      controls.update()
      renderer.render(scene, camera)
    }

    // 定义初始化方法
    function init() {
      
      
      initRenderer()
      initScene()
      initCamera()
      initMesh()
      animate()
    }

    init()

  </script>
</body>

</html>

六、全景看房地标添加

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>轨迹球控制与材质</title>
  <style>
    * {
      
      
      margin: 0;
      padding: 0;
    }

    canvas {
      
      
      display: block;
      height: 100%;
      width: 100%;
    }
  </style>
  <script src="./three.min.js"></script>
  <script src="./TrackballControls.js"></script>
</head>

<body>
  <script>
    // 定义全局变量
    let scene, camera, geometry, mesh, renderer, controls
    let sixPlane = []
    let spriteArrow = ""
    let raycaster = new THREE.Raycaster()
    const mouse = new THREE.Vector2()

    function onMouseMove(event) {
      
      
      // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;

    }
    window.addEventListener('mousemove', onMouseMove, false)

    // 鼠标点击 
    function mouseClickEvent(ev) {
      
      
      ev.preventDefault();
      // 射线捕获
      raycaster.setFromCamera(mouse, camera)

      const intersects = raycaster.intersectObjects([spriteArrow])

      if (intersects.length > 0) {
      
      
        changeScene()
      }
    }

    window.addEventListener('click', mouseClickEvent, false)

    // 初始化渲染器
    function initRenderer() {
      
      
      renderer = new THREE.WebGLRenderer({
      
       antialias: true })
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.setPixelRatio(window.devicePixelRatio)
      document.body.appendChild(renderer.domElement)
    }

    // 初始化场景
    function initScene() {
      
      
      scene = new THREE.Scene()
      const axesHelper = new THREE.AxesHelper(100)
      scene.add(axesHelper)
    }

    // 初始化相机
    function initCamera() {
      
      
      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
      camera.position.set(0, 0, 15)
      controls = new THREE.TrackballControls(camera, renderer.domElement)
      // 控制视觉位置
      controls.maxDistance = 2  // 最大距离
      controls.minDistance = 0  // 最小距离
    }

    // 初始化模型
    function initMesh() {
      
      

      // 利用精灵材质引入地面标记 
      new THREE.TextureLoader().load('img/icon.png', (texture) => {
      
      
        const spriteMaterial = new THREE.SpriteMaterial({
      
      
          map: texture
        })
        spriteArrow = new THREE.Sprite(spriteMaterial) //会固定位置
        spriteArrow.scale.set(0.1, 0.1, 0.1)
        spriteArrow.position.set(0.5, -1, -1.5)
        scene.add(spriteArrow)
      })

      sixPlane = createPlane(0)
      for (let i = 0; i < 6; i++) {
      
      
        scene.add(sixPlane[i])
      }
    }

    // 初始化动画
    function animate() {
      
      
      requestAnimationFrame(animate)
      controls.update()
      renderer.render(scene, camera)
    }

    // 定义初始化方法
    function init() {
      
      
      initRenderer()
      initScene()
      initCamera()
      initMesh()
      animate()
    }

    init()

    function createPlane(num) {
      
      
      const BoxGeometry = []
      // 前面
      const geometryF = new THREE.PlaneGeometry(4, 4)
      const materialF = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/' + num + '_f.jpg'),
        side: THREE.DoubleSide
      })
      const meshF = new THREE.Mesh(geometryF, materialF)
      meshF.rotation.y = 180 * Math.PI / 180
      meshF.position.z = 2
      BoxGeometry.push(meshF)

      // 后面
      const geometryB = new THREE.PlaneGeometry(4, 4)
      const materialB = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/' + num + '_b.jpg'),
        side: THREE.DoubleSide
      })
      const meshB = new THREE.Mesh(geometryB, materialB)
      // meshB.rotation.y = 180 * Math.PI / 180
      meshB.position.z = -2
      BoxGeometry.push(meshB)

      // 左侧 
      const geometryL = new THREE.PlaneGeometry(4, 4)
      const materialL = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/' + num + '_l.jpg'),
        side: THREE.DoubleSide
      })
      const meshL = new THREE.Mesh(geometryL, materialL)
      meshL.rotation.y = (-90) * Math.PI / 180
      meshL.position.x = 2
      BoxGeometry.push(meshL)

      // 右侧 
      const geometryR = new THREE.PlaneGeometry(4, 4)
      const materialR = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/' + num + '_r.jpg'),
        side: THREE.DoubleSide
      })
      const meshR = new THREE.Mesh(geometryR, materialR)
      meshR.rotation.y = (90) * Math.PI / 180
      meshR.position.x = -2
      BoxGeometry.push(meshR)

      // 上面
      const geometryU = new THREE.PlaneGeometry(4, 4)
      const materialU = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/' + num + '_u.jpg'),
        side: THREE.DoubleSide
      })
      const meshU = new THREE.Mesh(geometryU, materialU)
      meshU.rotation.x = (90) * Math.PI / 180
      meshU.rotation.z = (180) * Math.PI / 180
      meshU.position.y = 2
      BoxGeometry.push(meshU)

      // 下面
      const geometryD = new THREE.PlaneGeometry(4, 4)
      const materialD = new THREE.MeshBasicMaterial({
      
      
        map: new THREE.TextureLoader().load('img/' + num + '_d.jpg'),
        side: THREE.DoubleSide
      })
      const meshD = new THREE.Mesh(geometryD, materialD)
      meshD.rotation.x = (-90) * Math.PI / 180
      meshD.rotation.z = (180) * Math.PI / 180
      meshD.position.y = -2
      BoxGeometry.push(meshD)

      return BoxGeometry
    }

    function changeScene() {
      
      
      // 创建六个面 
      const sixBox = createPlane(2)
      const timer = setInterval(() => {
      
      
        camera.fov -= 1
        camera.updateProjectionMatrix()
        if (camera.fov == 20) {
      
      
          clearInterval(timer)
          camera.fov = 45
          camera.updateProjectionMatrix()
          for (let i = 0; i < 6; i++) {
      
      
            scene.remove(sixPlane[i])
          }
          sixPlane = sixBox
          for (let i = 0; i < 6; i++) {
      
      
            scene.add(sixPlane[i])
          }
          spriteArrow.visible = false
        }
      }, 50)
    }

  </script>
</body>

</html>

七、全景看房实现

猜你喜欢

转载自blog.csdn.net/woyebuzhidao321/article/details/129248048