mapbox结合threeJS载入3d模型,并实现点击事件

https://www.jianshu.com/p/ae8f9b338f80 地址参考代码如下:

<!DOCTYPE html>
<html>
<head>
    <title>Mapbox THREE.js raycaster test</title>
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <link rel='stylesheet' href='css/mapbox-gl.css' />
    <style>
        body { margin: 0; padding: 0; }
        html, body, #map { height: 100%; }
    </style>
</head>

<body>
<script src='js/three.min.js'></script>

<div id='map'></div>
<script src='js/mapbox-gl.js'></script>
<script>

  const blankStyle = {
    version: 8,
    name: 'BlankMap',
    sources: {},
    layers: [
      {
        id: 'background',
        type: 'background',
        paint: {
          // 'background-color': '#08294A' /* 背景颜色 */
          'background-color': 'rgba(255, 255, 255, 0)' /* 背景颜色-透明 */
        }
      }
    ]
  };

// This codepen attempts to use THREE.js's raycaster with a Mapbox custom layer. If I've done things correctly,
// hovering over the cube should turn it red. It seems though that the intersection is never detected.
// See: https://github.com/mapbox/mapbox-gl-js/issues/10595

mapboxgl.accessToken = 'pk.eyJ1IjoibmFnaXgiLCJhIjoiY2treGZoNzY5MHE1OTJ4bzQ5NmYyY2twNiJ9.ZX7a6VWavDoOMbDoRR7IOg';
var map = new mapboxgl.Map({
  container: 'map',
  zoom: 14,
  center: [139.7670, 35.6814],
  pitch: 30,
  style: blankStyle
});

const mouse = new THREE.Vector4(-1000, -1000, 1, 1);

// parameters to ensure the model is georeferenced correctly on the map
var modelOrigin = [139.7670, 35.6814];
var modelAltitude = 150;

var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
  modelOrigin,
  modelAltitude
);

// transformation parameters to position, rotate and scale the 3D model onto the map
var modelTransform = {
  translateX: modelAsMercatorCoordinate.x,
  translateY: modelAsMercatorCoordinate.y,
  translateZ: modelAsMercatorCoordinate.z,
  /* Since our 3D model is in real world meters, a scale transform needs to be
   * applied since the CustomLayerInterface expects units in MercatorCoordinates.
   */
  scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};

// configuration of the custom layer for a 3D model per the CustomLayerInterface
var customLayer = {
  id: '3d-model',
  type: 'custom',
  renderingMode: '3d',
  onAdd: function(map, gl) {
    this.camera = new THREE.PerspectiveCamera();
    this.scene = new THREE.Scene();
    var cube = new THREE.Mesh(
    	new THREE.BoxGeometry( 300, 300, 300 ),
        new THREE.MeshNormalMaterial()
    );
    this.scene.add(cube)
    let cube1 = cube.clone();
    cube1.material = new THREE.MeshNormalMaterial();
    cube1.translateX(1000);
    this.scene.add(cube1)

    this.map = map;

    // use the Mapbox GL JS map canvas for three.js
    this.renderer = new THREE.WebGLRenderer({
      canvas: map.getCanvas(),
      context: gl,
      antialias: true
    });

    this.renderer.autoClear = false;
    this.raycaster = new THREE.Raycaster();
  },
  render: function(gl, matrix) {
    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
        )
      );
    
    this.camera.projectionMatrix = m.clone().multiply(l);
    this.camera.matrixWorldInverse = new THREE.Matrix4();
    this.renderer.resetState();

    const freeCamera = this.map.getFreeCameraOptions();
    let cameraPosition = new THREE.Vector4(freeCamera.position.x, freeCamera.position.y, freeCamera.position.z, 1);
    cameraPosition.applyMatrix4(l.invert());
    let direction = mouse.clone().applyMatrix4(this.camera.projectionMatrix.clone().invert());
    direction.divideScalar(direction.w);
    this.raycaster.set(cameraPosition, direction.sub(cameraPosition).normalize());

    const intersects = this.raycaster.intersectObjects( this.scene.children );
    console.log('Intersection count:', intersects.length)

    for ( let i = 0; i < intersects.length; i ++ ) {
      intersects[ i ].object.material.wireframe = true;
    }
    
    this.renderer.render(this.scene, this.camera);

    for ( let i = 0; i < intersects.length; i ++ ) {
      intersects[ i ].object.material.wireframe = false;
    }
  }
};

map.on('load', function() {
  map.addLayer(customLayer);
  
  map.on('mousemove', function (event) {
    mouse.x = ( event.point.x / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.point.y / window.innerHeight ) * 2 + 1;
    map.triggerRepaint();
  });
});

</script>
</body>
</html>

上面代码运行后如果出现 Uncaught TypeError: this.renderer.resetState is not a function 或 Uncaught TypeError: l.invert is not a function相关问题,是引用的three.min.js版本不对,换下three.min.js版本解决。

MapboxThree.js 是两个独立的开源项目,可以结合使用来创建交互式地图和可视化效果。Mapbox 是一个提供地图数据和地图服务的平台,而 Three.js 是一个基于 WebGL3D 图形库。 结合 MapboxThree.js,你可以在地图上创建各种令人惊叹的视觉效果,例如在地图上展示 3D 模型、动态地图标记或者添加自定义的动画效果。 以下是一个简单的示例,展示如何在 Mapbox 地图上使用 Three.js 创建一个旋转的立方体: 1. 首先,引入 MapboxThree.js 的库文件,并创建一个容器来放置地图: ```html <div id="map"></div> ``` 2. 然后,在 JavaScript 中初始化地图,获取地图容器的大小,并创建一个 Three.js 场景: ```javascript mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; var map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/streets-v11', center: [0, 0], zoom: 1 }); var scene = new THREE.Scene(); ``` 3. 接下来,在场景中创建一个旋转的立方体: ```javascript var geometry = new THREE.BoxGeometry(1, 1, 1); var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); var cube = new THREE.Mesh(geometry, material); scene.add(cube); function animate() { requestAnimationFrame(animate); cube.rotation.x += 0.01; cube.rotation.y += 0.01; // 渲染 Three.js 场景 renderer.render(scene, camera); } animate(); ``` 4. 最后,将 Three.js 的渲染结果嵌入到 Mapbox 地图中: ```javascript var renderer = new THREE.WebGLRenderer({ alpha: true }); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; function render() { requestAnimationFrame(render); // 将 Mapbox 地图渲染到 Three.js 的纹理上 renderer.autoClear = false; renderer.clear(); renderer.render(scene, camera); // 将 Three.js 的渲染结果放置在地图上 map.triggerRepaint(); } map.on('load', function() { map.on('render', render); }); ``` 通过结合 MapboxThree.js,你可以根据自己的需求创建更复杂的交互式地图和可视化效果。希望这个例子能帮助到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值