-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMapboxLayer.js
More file actions
108 lines (100 loc) · 4.1 KB
/
MapboxLayer.js
File metadata and controls
108 lines (100 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/** https://docs.mapbox.com/mapbox-gl-js/api/#customlayerinterface **/
export class MapboxLayer {
constructor(options) {
this.options = options;
this.isReady = false;
this._callbacks = [];
this.id = options.id;
this.renderingMode = "3d";
this.type = "custom";
this.mercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat([this.options.longitude, this.options.latitude], this.options.altitude);
this.rotationMatrix = BABYLON.Matrix.RotationX(Math.PI / 2);
this.translateMatrix = BABYLON.Matrix.Identity().setTranslationFromFloats(this.mercatorCoordinate.x, this.mercatorCoordinate.y, this.mercatorCoordinate.z);
let scaleFactor = this.mercatorCoordinate.meterInMercatorCoordinateUnits();
this.scaleMatrix = BABYLON.Matrix.Scaling(scaleFactor, scaleFactor, scaleFactor);
this.worldMatrix = this.scaleMatrix.multiply(this.rotationMatrix.multiply(this.translateMatrix));
}
_setupScene(scene) {
scene.activeCamera = new BABYLON.Camera("mapbox-Camera", new BABYLON.Vector3(), scene);
scene.autoClear = false;
scene.detachControl();
return scene;
}
_createScene(callback) {
let res = callback.call(this, this.engine);
if (typeof res.then === 'function') {
res.then( (scene) => {
this.scene = this._setupScene(scene);
this.isReady = true;
this._callbacks.forEach( (callback) => {
callback.call(this, this.scene, this.map);
});
this._callbacks.length = 0;
});
}
else {
this.scene = this._setupScene(res);
this.isReady = true;
this._callbacks.forEach( (callback) => {
callback.call(this, this.scene, this.map);
});
this._callbacks.length = 0;
}
}
ready(callback) {
if (this.isReady) {
callback.call(this, this.scene);
}
else {
this._callbacks.push(callback);
}
}
whenReadyAsync () {
return new Promise( (resolve) => {
this.ready(function () {
resolve(this.scene);
});
});
};
pick(x, y) {
// https://docs.mapbox.com/mapbox-gl-js/api/events/#mapmouseevent
if (this.isReady) {
let ray = this.scene.createPickingRay(x, y, BABYLON.Matrix.Identity(), this.scene.activeCamera);
return this.scene.pickWithRay(ray);
}
else {
throw new Error('MapboxLayer.pick() - scene is not ready');
}
};
/** Mapbox Custom Layer **/
/**
* Called when the layer has been added to the Map. (https://docs.mapbox.com/mapbox-gl-js/api/#customlayerinterface#onadd)
* @param map The Map this custom layer was just added to.
* @param gl The gl context for the map.
*/
onAdd(map, gl) {
this.map = map;
this.engine = new BABYLON.Engine(gl, true);
// the only way i found to resize the engine correctly...
window.dispatchEvent(new Event('resize'));
this._createScene(this.options.createScene);
};
/**
* Called during a render frame allowing the layer to draw into the GL context. (https://docs.mapbox.com/mapbox-gl-js/api/#customlayerinterface#render)
* @param gl The gl context for the map
* @param matrix The map's camera matrix. It projects spherical mercator coordinates to gl coordinates.
*/
render(gl, matrix) {
if (this.scene) {
var projection = BABYLON.Matrix.FromArray(matrix);
// @ts-ignore
projection._m = matrix; // https://forum.babylonjs.com/t/mapbox-gl-to-babylon-camera-projection/9972/16?u=sharp
this.projectionMatrix = this.worldMatrix.multiply(projection);
this.scene.activeCamera.freezeProjectionMatrix(this.projectionMatrix);
this.scene.render(false);
this.engine.wipeCaches(true);
}
// https://docs.mapbox.com/mapbox-gl-js/api/#map#triggerrepaint
this.map.triggerRepaint();
};
}