我的脚本的主要代码是在地图上设置 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);
});
但是,这行不通。
感谢您的帮助
同样的问题,有线索吗?我无法将点击事件添加到 3D 对象。图层点击事件在 3D 模式下正常工作