Skip to content

GLB或GLTF格式

示例

示例源码
tsx
import React, { useCallback, useEffect, useRef, useState } from 'react'
import ReactDOM from 'react-dom'
import * as THREE from 'three'
import { GLTFLoader } from 'GLTFLoader'
import { MbMap, MbTiandituLayer } from '@mapbox-react/core'

const App = () => {
  const [mapCenter] = useState([116.3466, 39.8704])
  const [zoom, setZoom] = useState(16)
  const [pitch, setPitch] = useState(45)
  const mapInst = useRef<any>()

  let map: any
  const altitude = 0
  let mixers: THREE.AnimationMixer[] = []
  let clock = new THREE.Clock()

  const mapCreated = (mapbox: any) => {
    map = mapbox
    mixers = []
    clock = new THREE.Clock()
  }
  const add3DLayer = () => {
    loaderModels()
  }

  const loaderModels = () => {
    const loader = new GLTFLoader()
    loader.load(
      `https://mapbox-web.github.io/mapbox-react/gltf/Flamingo/Flamingo.glb`,
      (gltf) => {
        const bird = gltf.scene

        bird.scale.multiplyScalar(150)
        bird.rotation.y = -1
        bird.rotation.x = Math.PI * 1.5

        const mixer = new THREE.AnimationMixer(gltf.scene.children[0])
        mixer.clipAction(gltf.animations[0]).setDuration(1).play()
        mixers.push(mixer)

        addThreeLayer(bird)
      }
    )
  }
  const addThreeLayer = (bird) => {
    const threeLayer = new map.mapboxgl.supermap.ThreeLayer('threeLayer')
    threeLayer.on('initialized', render)
    let light: THREE.PointLight
    function render() {
      const renderer = threeLayer.getThreeRenderer(),
        scene = threeLayer.getScene(),
        camera = threeLayer.getCamera()

      light = new THREE.PointLight(0xffffff, 0.8)
      light.position.copy(camera.position)
      scene.add(light)
      scene.add(new THREE.AmbientLight(0xffffff))

      threeLayer.setPosition(bird, mapCenter)
      bird.translateY(500)

      scene.add(bird)
        ; (function animate() {
          bird.rotation.y += 0.01

          const delta = clock.getDelta()
          for (const mixer of mixers) {
            mixer.update(delta)
          }
          renderer.render(scene, camera)

          requestAnimationFrame(animate)
        })()
    }

    threeLayer.on('render', () => {
      light && light.position.copy(threeLayer.renderer.camera.position)
    })
    map.addLayer(threeLayer)
  }

  return (
    <div className="map-wrapper">
      <MbMap
        ref={mapInst}
        center={mapCenter}
        zoom={zoom}
        pitch={pitch}
        onCreated={mapCreated}
      >
        <MbTiandituLayer types={['vec', 'cva']} onCreated={add3DLayer} />
      </MbMap>
    </div>
  )
}

ReactDOM.render(<App />, document.querySelector('#root'))