1、Dom元素:
2、import引入:
3、data(定义map,camera(镜头),scene(场景),stats(),mixer(),clock(时钟),customLayer(MapBox自定义图层)):
4、methods(定位模型位置,创建自定义图层,加载模型,设置场景,设置镜头,设置光照,地图重新渲染将自定义层的模型加载到地图上,解析fbx模型骨骼动画,通过threejs的clock控件获得两帧之间的时间间隔,执行再次渲染函数render,渲染下一帧。):
methods: {
initFBX() {
var mapSecond = this.map
// 用于确保模型在地图上正确地理参照的参数
var modelOrigin = [148.9818395, -35.3985293]
var modelAltitude = 0
var modelRotate = [Math.PI / 2, 0, 0]
var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude)
// 将三维模型定位、旋转和缩放到地图上的变换参数
var modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
/* Since our 3D model is in real world meters, a scale transform needs to be
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
* 坐标转换,转为WebMercator
*/
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits(),
}
var that = this
// 为三维模型配置自定义图层
this.customLayer = {
id: '3d-model',
type: 'custom',
source: 'radar',
renderingMode: '3d',
onAdd: function (map, gl) {
that.camera = new THREE.Camera()
that.scene = new THREE.Scene()
that.clock = new THREE.Clock()
// 创建光源
//环境光,无光照角度变化效果
var ambient = new THREE.AmbientLight(0xffffff)
that.scene.add(ambient)
//平行光,比如太阳光
// var directionalLight = new THREE.DirectionalLight(0xffffff)
// directionalLight.position.set(0, -70, 100).normalize()
// this.scene.add(directionalLight)
// var directionalLight2 = new THREE.DirectionalLight(0xffffff)
// directionalLight2.position.set(0, 70, 100).normalize()
// this.scene.add(directionalLight2)
// use the three.js GLTF loader to add the 3D model to the three.js scene
var loader = new FBXLoader()
loader.load(
'http://219.146.77.222:18024/gis/Map/JumpingDown.fbx',
function (fbx) {
console.log(fbx.animations)
that.scene.add(fbx)
fbx.translateY(-80)
that.mixer = new THREE.AnimationMixer(fbx)
var AnimationAction = that.mixer.clipAction(fbx.animations[0])
AnimationAction.play() //播放动画
}.bind(that)
)
// use the Mapbox GL JS map canvas for three.js
that.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true,
})
that.renderer.autoClear = false
that.clock = new THREE.Clock()
},
render: function (gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX)
var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY)
var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ)
var m = new THREE.Matrix4().fromArray(matrix)
var l = new THREE.Matrix4()
.makeTranslation(modelTransform.translateX, modelTransform.translateY, modelTransform.translateZ)
.scale(new THREE.Vector3(modelTransform.scale, -modelTransform.scale, modelTransform.scale))
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ)
that.camera.projectionMatrix = m.multiply(l)
that.renderer.state.reset()
that.renderer.render(that.scene, that.camera)
if (that.mixer !== null) {
//clock.getDelta()方法获得两帧的时间间隔
// 更新混合器相关的时间
that.mixer.update(that.clock.getDelta())
}
},
}
//重新渲染地图
mapSecond.on('style.load', () => {
mapSecond.addLayer(this.customLayer, 'waterway-label')
window.requestAnimationFrame(this.render)
})
},
render(gl, matrix) {
this.map.setFeatureState(
{
source: 'radar',
sourceLayer: 'my-source-layer',
id: '3d-model',
},
{
hover: true,
}
)
try {
} catch {}
window.requestAnimationFrame(this.render)
},
},
5、mounted(加载地图,执行initFBX方法):
mounted() {
mapboxgl.accessToken ='输入自己的token'
this.map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v11', // stylesheet location
center: [148.9819, -35.39847], // starting position [lng, lat]
zoom: 18, // starting zoom
pitch: 60,
antialias: true, // create the gl context with MSAA antialiasing, so custom layers are antialiased
})
this.initFBX()
}
6、style(定义地图样式):