Mapbox 具有自己的单击事件的多个 3D 模型

问题描述 投票:0回答:1

我的脚本的主要代码是在地图上设置 3D 模型的 Mapbox 示例 (https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/)。我修改此代码以在我的地图上设置 3 个 3D 模型,这有效:

<!doctype html>

<html lang="en">
    <head>
        <meta charset="utf-8">
        <link href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.1/mapbox-gl.css" rel="stylesheet" />
        <style>
            html, body, #mapContainer {
                height: 100%;
                margin: 0;
            }
        </style>
    </head>

    <body>

        <div id="mapContainer"></div>


        <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.1/mapbox-gl.js'></script>
        <script src="https://unpkg.com/[email protected]/build/three.min.js"></script>
        <script src="https://unpkg.com/[email protected]/examples/js/loaders/GLTFLoader.js"></script>
        <script>

        const THREE = window.THREE;

        mapboxgl.accessToken = 'MY_TOKEN';

        const map = new mapboxgl.Map({
            container: 'mapContainer',
            style: 'mapbox://styles/mapbox/light-v9',
            center: [-100.52, 37.67],
            zoom: 18,
            pitch: 36,
            hash: true,
        });

        // Add zoom and rotation controls to the map.
        map.addControl(new mapboxgl.NavigationControl());



function BuildLayer(map, id, LAT, LON){

            // parameters to ensure the model is georeferenced correctly on the map
                var modelOrigin = [LAT, LON];
                var modelAltitude = 0;
                var modelRotate = [Math.PI / 2, 0, 0];

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


                    modelScale = 2.8e-8; modelSkin = 'https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf';


            // transformation parameters to position, rotate and scale the 3D model onto the map
                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.
                 */
                    scale: modelScale // modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
            };


            var customLayer = {
                id: 'Playertower' + id,
                type: 'custom',
                renderingMode: '3d',
                source: 'Tower',



                onAdd: function (map, gl) {
                    this.camera = new THREE.Camera();
                    this.scene = new THREE.Scene();

                    // create two three.js lights to illuminate the model
                    var directionalLight = new THREE.DirectionalLight(0xffffff);
                    directionalLight.position.set(0, -70, 100).normalize();
                    directionalLight.target.position.set(6000, 0, 3000);
                    this.scene.add(directionalLight);

                    var directionalLight2 = new THREE.DirectionalLight(0xffffff);
                    directionalLight2.position.set(0, 70, 100).normalize();
                    directionalLight2.target.position.set(6000, 0, 3000);
                    this.scene.add(directionalLight2);

                    // use the three.js GLTF loader to add the 3D model to the three.js scene
                    var loader = new THREE.GLTFLoader();
                    loader.load(
                        modelSkin,  // Skin ausgeben
                        function (gltf) {

                            this.scene.add(gltf.scene);


                        }.bind(this)
                    );
                    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;
                },
                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);

                    this.camera.projectionMatrix = m.multiply(l);
                    this.renderer.state.reset();
                    this.renderer.render(this.scene, this.camera);
                    this.map.triggerRepaint();


                }
            };



            return customLayer;
        }


        const cities = [
            {
                name: 'New York',
                coordinatesLat:  -100.5201,
                coordinatesLon:  37.6701,
            },
            {
                name: 'Washington, D.C.',
                coordinatesLat:  -100.5204,
                coordinatesLon:  37.6701,
            },
            {
                name: 'Chicago',
                coordinatesLat:  -100.5207,
                coordinatesLon:  37.6701,
            }
        ];



        map.on('style.load', () => {
            cities.forEach((city) => {

                customLayer = new BuildLayer(map, city.name,  city.coordinatesLat, city.coordinatesLon );
                map.addLayer(customLayer, 'waterway-label');

            })




        });
         

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

如何修改此代码来为每个 CustomLayer 设置单击事件?另外,您单击模型 2,警报窗口会显示“这是模型 2”等?

我测试过

                map.on('click', 'Playertower', function(e) {
                    var layerId = e.features[0].properties.id;
                    alert('Layer ID: ' + layerId);
                });

但是,这行不通。

感谢您的帮助

javascript mapbox openstreetmap 3d-model
1个回答
0
投票

同样的问题,有线索吗?我无法将点击事件添加到 3D 对象。图层点击事件在 3D 模式下正常工作

© www.soinside.com 2019 - 2024. All rights reserved.