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版本解决。