mapbox加载3D模型添加点击事件

165 阅读1分钟
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Add a 3D model with threebox</title>
    <meta
      name="viewport"
      content="initial-scale=1,maximum-scale=1,user-scalable=no"
    />
    <link
      href="https://api.mapbox.com/mapbox-gl-js/v3.10.0/mapbox-gl.css"
      rel="stylesheet"
    />
    <script src="https://api.mapbox.com/mapbox-gl-js/v3.10.0/mapbox-gl.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
      }
      #map {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <script
      src="https://cdn.jsdelivr.net/gh/jscastro76/threebox@v.2.2.2/dist/threebox.min.js"
      type="text/javascript"
    ></script>
    <link
      href="https://cdn.jsdelivr.net/gh/jscastro76/threebox@v.2.2.2/dist/threebox.css"
      rel="stylesheet"
    />
    <div id="map"></div>
    <script>
      const glbUrl =
        "https://docs.mapbox.com/mapbox-gl-js/assets/metlife-building.gltf"; // 你的3D模型
      const scale = 0; // 模型的scale
      const options = {
        // 将一些属性抽取成为一个对象
        obj: glbUrl, // 上面定义的模型
        type: "gltf", // 模型格式
        scale: { x: scale, y: scale, z: 0 }, // 设置x,y,z轴上的scale大小
        units: "meters", // 指定模型的单位长度,这里尺寸单位是米
        rotation: { x: 0, y: 0, z: 0 }, // 旋转角度
      };
      // TO MAKE THE MAP APPEAR YOU MUST
      // ADD YOUR ACCESS TOKEN FROM
      // https://account.mapbox.com
      mapboxgl.accessToken =
        "pk.eyJ1IjoiaHVhbmdsaWkiLCJhIjoiY2wwM2E4a2drMDVrZjNrcGRucHIxOHo0cyJ9.0ecG5KGQE6R-SmhxvLvhHg";
      const init = () => {
        map = new mapboxgl.Map({
          container: "map",
          center: [114.33, 30.57],
          zoom: 14, // 地图起始比例
        });

        map.on("load", () => {
          // 地图加载完成后执行
          // 创建一个 Three.js 场景的实例
          tb = window.tb = new Threebox(
            map,
            map.getCanvas().getContext("webgl"),
            {
              defaultLights: true, // 默认光照
            }
          );

          // 添加 3D 模型图层
          map.addLayer({
            id: "custom-threebox-model",
            type: "custom", // 自定义图层
            renderingMode: "3d", // 3D 渲染模式
            onAdd: function () {
              // 图层添加时执行
              tb.loadObj(options, (model) => {
                // 加载 3D 模型
                model_Value = model;
                model_Value.setRotation({ x: 0, y: 0, z: 0 }); // 设置旋转角度
                model_Value.setCoords([114.33, 30.57, 100]); // 设置经纬度和高度
                tb.add(model_Value); // 添加到场景中
              });
            },
            render: function () {
              tb.update(); // 每次渲染时更新场景
            },
          });

          // 监听点击事件
          map.on("click", (e) => {
            const mousePos = new THREE.Vector2(
              (e.point.x / map.getCanvas().width) * 2 - 1,
              -(e.point.y / map.getCanvas().height) * 2 + 1
            );

            // 创建射线投射器
            const raycaster = new THREE.Raycaster();
            raycaster.setFromCamera(mousePos, tb.camera); // 使用相机和鼠标位置更新射线

            // 获取点击位置在 Three.js 中的模型
            const intersects = raycaster.intersectObject(model_Value, true); // 检查是否与模型发生碰撞

            if (intersects.length > 0) {
              const object = intersects[0].object;
              console.log("Clicked on:", object); // 输出被点击的物体
              object.material.color.set(0xff0000); // 让点击的物体变成红色,或者执行其他操作
            }
          });
        });
      };
      init();
    </script>
  </body>
</html>