Threebox works by adding a Three.js scene to Mapbox GL, creating a new Mapbox GL custom layer that implements CustomLayerInterface. The custom layer API takes a fair amount of finessing to be useful, and Threebox tackles several hurdles to getting Three.js and Mapbox GL to work together.
Threebox contains +20 examples to showcase most of its features. Check them out to have a glance of what is possible.
To run them, create a config.js
file with your Mapbox-gl-js access token, in the same folder and in the format of the template.
- 01-basic.html
- 02-line.html
- 03-tube.html
- 04-mercator.html
- 05-logistics.html
- 06-object3d.html
- 07-alignmentTest.html
- 08-3dbuildings.html
- 09-raycaster.html
- 10-stylechange.html
- 11-animation.html
- 12-add3dmodel.html
- 13-eiffel.html
- 14-buildingshadow.html
- 15-performance.html
- 16-multilayer.html
- 17-azuremaps.html
- 18-extrusions.html
- 19-fixedzoom.html
- 20-game.html
- 21-terrain.html
- Vue.js sample
You can use threebox in three different ways.
Add threebox to your project via npm package :
npm install threebox-plugin
Then you will need to import Threebox object in your code. Depending your javascript framework this might be different.
import { Threebox } from 'threebox-plugin/dist/threebox';
Download the bundle from dist/threebox.js
or dist/threebox.min.js
and include it in a <script>
tag on your page.
If you want to use styles predefined, add the link to the cascade style sheet, just ensure the src
and href
attributes are pointing to relative or absolute url path.
<script src="../dist/threebox.js" type="text/javascript"></script>
<link href="./css/threebox.css" rel="stylesheet" />
Threebox can be also used from different public CDNs:
This CDN has the particularity that always requires the version of the package to download individual files.
<script src="https://cdn.jsdelivr.net/gh/jscastro76/[email protected]/dist/threebox.min.js" type="text/javascript"></script>
<link href="https://cdn.jsdelivr.net/gh/jscastro76/[email protected]/dist/threebox.css" rel="stylesheet" />
Despite this CDN admits version, if omitted, it will download always the last one published.
<script src="https://unpkg.com/threebox-plugin/dist/threebox.min.js" type="text/javascript"></script>
<link href="https://unpkg.com/threebox-plugin/dist/threebox.css" rel="stylesheet" />
For an specific version (i.e. v2.2.1) use the followin:
<script src="https://unpkg.com/[email protected]/dist/threebox.min.js" type="text/javascript"></script>
<link href="https://unpkg.com/[email protected]/dist/threebox.css" rel="stylesheet" />
The instance of Threebox will be used normally across the full page, so it's recommended to be created at window
scope to be used as a global variable.
Creating a global instance might be producing memory leaks when you navigate to other pages without disposing properly the resources. You can use tb.dispose
method to fully dispose the instance of Threebox but also all mapbox and three.js resources together.
var tb = new Threebox(map, glContext [, options])
Sets up a Threebox scene using an Mapbox map and a WebGLRenderingContext, both of them can be obtained from Mapbox GL map instance.
options
param is optional and can contain the following values:
option | required | default | type | purpose |
---|---|---|---|---|
defaultLights |
no | false | boolean | Whether to add some default lighting to the scene. If no lighting added, most objects in the scene will render as black |
realSunlight |
no | false | boolean | It sets lights that simulate Sun position for the map center coords map.getCenter and user local datetime new Date() . This sunlight can be updated through tb.setSunlight method. It calls internally to suncalc module. |
realSunlightHelper |
no | false | boolean | It sets if a light helper will be shown when realSunlight is true. |
passiveRendering |
no | true | boolean | Color of line. Unlike other Threebox objects, this color will render on screen precisely as specified, regardless of scene lighting |
enableSelectingFeatures |
no | false | boolean | Enables the Mouseover and Selection of fill-extrusion features. This will fire the event SelectedFeatureChange |
enableSelectingObjects |
no | false | boolean | Enables the Mouseover and Selection of 3D objects. This will fire the event SelectedChange . This value will set the options.bbx value of the objects created. |
enableDraggingObjects |
no | false | boolean | Enables to the option to Drag a 3D object. This will fire the event ObjectDragged where draggedAction = 'translate' or draggedAction = 'altitude' |
enableRotatingObjects |
no | false | boolean | Enables to the option to Drag a 3D object. This will fire the event ObjectDragged where draggedAction = 'rotate' |
enableTooltips |
no | false | boolean | Enables the default tooltips on fill-extrusion features and 3D Objects |
enableHelpTooltips |
no | false | boolean | Enables the default help tooltips when an object is being moved, rotated or measured. |
multiLayer |
no | false | boolean | Enables the option for multi layer pages where a default layer will be created internally that will manage the tb.update calls |
orthographic |
no | false | boolean | Enables the option to set a THREE.OrthographicCamera instead of a THREE.PerspectiveCamera which is the default in Mapbox |
fov |
no | ThreeboxConstants.FOV_DEGREES | number | Enables to set the FOV of the default THREE.PerspectiveCamera . This value has no effect if orthographic: true |
sky |
no | false | boolean | It sets a built-in atmospheric layer initially set with the time and the map center position. This layer is automatically updated if realSunlight is also true, but it can be updated separately through tb.updateSunSky(tb.getSunSky()) method call. |
terrain |
no | false | boolean | It sets a built-in terrain layer initially set with the time and the map center position. This layer is automatically updated if realSunlight is also true, but it can be updated separately through tb.updateSunSky(tb.getSunSky()) method call. |
To render Threebox scene, first is needed to create a CustomLayerInterface, and then add the 3D objects to render at onAdd
function.
Second, you need to call recursively to tb.update();
method from
CustomLayerInterface render
function.
Threebox then automatically synchronizes the camera movement and events between Three.js and Mapbox GL JS.
WebGLRenderingContext instance can be obtained in different ways. The most usual one is to get the context from the instance of the member onAdd(map, gl)
.
This method is quick and easy, but it implies that it's created only in every call to the method addLayer(layer[, beforeId])
map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, gl) {
window.tb = new Threebox(
map,
gl, //get the context from Mapbox
{ defaultLights: true }
);
var geometry = new THREE.BoxGeometry(30, 60, 120);
let cube = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({ color: 0x660000 }));
cube = tb.Object3D({ obj: cube, units: 'meters' });
cube.setCoords([-3.460539968876, 40.4849214450]);
tb.add(cube);
},
render: function (gl, matrix) {
tb.update(); //update Threebox scene
}
}
The second way is to get the context from the canvas of the Mapbox GL map map.getCanvas().getContext('webgl')
.
In this way the creation of the Threebox can be instantiated separately from the addLayer
method that is more useful for multiple layers and objects. In this way the instace will exist even if there are no custom layers created, so you have to take care to properly dispose the resources.
window.tb = new Threebox(
map,
map.getCanvas().getContext('webgl'), //get the context from the map canvas
{ defaultLights: true }
);
map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, gl) {
var geometry = new THREE.BoxGeometry(30, 60, 120);
let cube = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({ color: 0x660000 }));
cube = tb.Object3D({ obj: cube, units: 'meters' });
cube.setCoords([-3.460539968876, 40.4849214450]);
tb.add(cube);
},
render: function (gl, matrix) {
tb.update(); //update Threebox scene
}
}
One of the most powerful capabilities of Threebox is the option to load 3D models from external files in different formats (OBJ/MTL, GLTF/GLB, FBX, DAE are supported). Once the model is loaded and added to Threebox, the object is powered by default with some methods, interactions, events and animations.
Once the object is loaded and added to Threebox instance, it can be selectable, draggable and rotable (over the z axis)
with the mouse if Threebox instance properties enableSelectingObjects
, enableDraggingObjects
and
enableRotatingObjects
are set to true
.
- To drag an object you have to select the object and then press SHIFT key and move the mouse to change its Lnglat position, and CTRL key to change its altitude.
- To rotate and object you have to select the object and then press ALT key and move the mouse. The object will always rotate over its defined center.
Any 3D object (including 3D extrusions created through fill-extrusion mapbox layers) will have a tooltip if the Threebox instance property tb.enableTooltips
is set to true.
Here below is the simplest sample to load a 3D model:
<!doctype html>
<head>
<title>Simplest sample of 3D Model loading</title>
<script src="../dist/threebox.js" type="text/javascript"></script>
<script src="https://api.mapbox.com/mapbox-gl-js/v.1.11.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v.1.11.1/mapbox-gl.css" rel="stylesheet" />
<style>
body, html {
width: 100%;
height: 100%;
margin: 0;
background: black;
}
#map {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id='map' class='map'></div>
<script>
mapboxgl.accessToken = 'Paste here your mapbox access token key';
var origin = [-122.47920912, 37.716351775];
var destination, line;
var soldier;
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/outdoors-v11',
center: origin,
zoom: 18,
pitch: 60,
bearing: 0
});
map.on('style.load', function () {
map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, mbxContext) {
window.tb = new Threebox(
map,
mbxContext,
{ defaultLights: true }
);
var options = {
obj: '/3D/soldier/soldier.glb',
type: 'gltf',
scale: 1,
units: 'meters',
rotation: { x: 90, y: 0, z: 0 } //default rotation
}
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
tb.add(soldier);
})
},
render: function (gl, matrix) {
tb.update();
}
});
})
</script>
</body>
Here is the full list of all the methods exposed by Threebox.
In all the samples below, the instance of Threebox will be always referred as tb
.
tb.add(obj [, layerId, sourceId])
method to add an object to Threebox scene. It will add it to tb.world.children
array.
async tb.clear([layerId, dispose])
This method removes any children from tb.world
. If it receives a layerId
this only affects to the objects in that layer.
If it receives true
as a param, it will also call internally obj.dispose
to dispose all the resources reserved by those objects.
tb.createSkyLayer()
This internal method creates a new sky atmospheric layer, it's interally used by the property tb.sky
.
tb.createTerrainLayer()
This internal method creates a new terrain layer, it's interally used by the property tb.terrain
.
tb.defaultLights()
This method creates the default illumination of the Threebox scene
.
By default, it creates a THREE.AmbientLight
and assigned to tb.lights.ambientLight
two THREE.DirectionalLight
.
These lights can be overriden manually adding custom lights to the Threebox scene
.
tb.dispose() : Promise (async)
If Threebox is being used as a part of a web application, it's recommended to dispose explicitely the instance of Threebox whenever
its instance is not going to be used anymore or before navigating to another page that does not include Threebox, otherwise it's
likely that you will face memory leaks issues not only due to Threebox, but also due to the internal use of Mapbox GL and Three.js instances needed to manage the objects.
To dispose completely all the resources and memory Threebox can acumulate, including the internal resources from Three.js and Mapbox GL, it's needed to invoke the dispose
method.
This method will go through the scene created to dispose every object, geometry, material and texture in Three.js, then it will dispose all the resources from Mapbox GL, including the WebGLRenderingContext
and itselft the Threebox instance.
After calling to this method, Threebox and Mapbox GL map instances will be fully disposed so it's only recommended before navigating to other pages.
tb.findParent3DObject(mesh) : Object3D
This method finds the parent Object3D in the Threebox scene by a mesh. This method is used in combination with tb.queryRenderedFeatures
that returns an Array of objects, most of them Meshes where the THREE.Raycaster
has interesected.
tb.getFeatureCenter(feature, model, level): lnglat
Calculate the center of a feature geometry coordinates, including the altitude (in meters) for a given GeoJson feature that can include or not a 3D model loaded and for a given level.
This method calls internally to tb.getObjectHeightOnFloor
and can be used for both a Poligon feature for a Fill Extrusion or a Point feature for a 3D model.
tb.getObjectHeightOnFloor(feature, obj, level) : number
Calculate the altitude (in meters) for a given GeoJson feature that can include or not a 3D model loaded and for a given level. This method can be used for both a Poligon feature for a Fill Extrusion or a Point feature for a 3D model.
tb.getSunPosition(date, coords)
This method gets Sun light position (azimuth, altitude) based on suncalc.js.
module which calculates the sun position for a given date, time, lng, lat combination.
tb.getSunSky(date, sunPos)
This method gets Sun sky layer position [azimuth, altitude]
based on suncalc.js.
module which calculates the sun position for a given date, time, lng, lat combination.
If date
is provided, it will use that, otherwise it will use new Date()
. If sunPos
is provided, it will use that, otherwise it will calculate it based on map.getCenter() calling tb.getSunPosition
method.
tb.getSunTimes(date, coords)
This method gets Sun times based on suncalc.js.
module which calculates the times for the different light phases (sunrise, sunset, etc..) from a given datetime, lng, lat and alt. This is used to change the map style based on day/night hour.
Returns an object with the following properties (each is a Date
object):
Property | Description |
---|---|
sunrise |
sunrise (top edge of the sun appears on the horizon) |
sunriseEnd |
sunrise ends (bottom edge of the sun touches the horizon) |
goldenHourEnd |
morning golden hour (soft light, best time for photography) ends |
solarNoon |
solar noon (sun is in the highest position) |
goldenHour |
evening golden hour starts |
sunsetStart |
sunset starts (bottom edge of the sun touches the horizon) |
sunset |
sunset (sun disappears below the horizon, evening civil twilight starts) |
dusk |
dusk (evening nautical twilight starts) |
nauticalDusk |
nautical dusk (evening astronomical twilight starts) |
night |
night starts (dark enough for astronomical observations) |
nadir |
nadir (darkest moment of the night, sun is in the lowest position) |
nightEnd |
night ends (morning astronomical twilight starts) |
nauticalDawn |
nautical dawn (morning nautical twilight starts) |
dawn |
dawn (morning nautical twilight ends, morning civil twilight starts) |
async tb.loadObj(options, callback(obj));
This async method loads a 3D model in different formats from its respective files.
It automatically caches the first object for each resource url so the next instances are returned from obj.duplicate
.
Note that unlike all the other object classes, this is asynchronous, and returns the object as an argument of the callback function.
Internally, uses THREE.OBJLoader
, THREE.FBXLoader
, THREE.GLTFLoader
or THREE.ColladaLoader
respectively to fetch the assets to each 3D format. THREE.FBXLoader
also dependes on Zlib to open compressed files which this format is based on.
[jscastro] IMPORTANT: There are breaking changes in this release regarding the attributes below comparing to @peterqliu original Threebox.
option | required | default | type | description |
---|---|---|---|---|
type |
yes | "mtl" | string ("mtl" , "gltf" , "fbx" , "dae" ) |
BREAKING CHANGE: Type is now required |
obj |
yes | NA | string | BREAKING CHANGE: URL path to asset's .obj, .glb, .gltf, .fbx, .dae file. |
mtl |
no | NA | string | URL path to assets .mtl files needed for OBJ models respectively |
bin |
no | NA | string | URL path to assets .bin files needed for GLTF models respectively |
units |
no | scene | string ("scene" or "meters" ) |
"meters" is recommended for precision. Units with which to interpret the object's vertices. If meters, Threebox will also rescale the object with changes in latitude, to appear to scale with objects and geography nearby. |
rotation |
no | 0 | number or {x, y, z} | Rotation of the object along the three axes, to align it to desired orientation before future rotations. Note that future rotations apply atop this transformation, and do not overwrite it. rotate attribute must be provided in number or per axis ((i.e. for an object rotated 90 degrees over the x axis rotation: {x: 90, y: 0, z: 0} |
scale |
no | 1 | number or {x, y, z} | Scale of the object along the three axes, to size it appropriately before future transformations. Note that future scaling applies atop this transformation, rather than overwriting it. scale attribute must be provided in number or per axis ((i.e. for an object transformed to 3 times higher than it's default size scale: {x: 1, y: 1, z: 3} |
anchor |
no | bottom-left |
string () | This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top , bottom , left , right , center , top-left , top-right , bottom-left , bottom-right . Default value is bottom-left . auto value will do nothing, so the model will use the anchor defined in the model, whatever it is. |
adjustment |
no | 1 | {x, y, z} | 3D models are often not centered in their axes so the object positions and rotates wrongly. adjustment param must be provided in units per axis (i.e. adjustment: {x: 0.5, y: 0.5, z: 0} ), so the model will correct the center position of the object |
normalize |
no | true | bool | This param allows to normalize specular values from some 3D models |
feature |
no | 1 | GeoJson feature | GeoJson feature instance. properties object of the GeoJson standard feature could be used to store relavant data to load and paint many different objects such as camera position, zoom, pitch or bearing, apart from the attributes already usually used by Mapbox GL examples such as height , base_height , color |
tooltip |
no | false | bool | This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips |
bbox |
no | false | bool | This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects |
raycasted |
no | true | bool | This param allows to hide an object from raycast individually |
clone |
no | true | bool | This param allows to load an object without cloning it by default, but it will reduce performance because the new object will consume extra memory as no textures will be cloned. Some objects could require full new instances when animations and textures don't work well with cloning, then clone: false will solve the problem. By default clone param is true. |
defaultAnimation |
no | 0 | number | This allows to assign by param a default animation. Igneored if the object does not contain animations |
callback |
yes | NA | function | A function to run after the object loads. The first argument will be the successfully loaded object, and this is normally used to finish the configuration of the model and add it to Threebox scene through tb.add() method. |
map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, gl) {
window.tb = new Threebox(
map,
gl,
{
defaultLights: true
enableSelectingFeatures: true, //omit or change this to false to disable fill-extrusion features selection
enableSelectingObjects: true, //omit or change this to false to disable 3D objects selection
enableDraggingObjects: true, //omit or change this to false to disable 3D objects drag & move once selected
enableRotatingObjects: true, //omit or change this to false to disable 3D objects rotation once selected
enableTooltips: true, //omit or change this to false to disable default tooltips on fill-extrusion and 3D models
}
);
var options = {
obj: '/3D/soldier/soldier.glb', //the model url, relative path to the page
type: 'gltf', //type enum, glb format is
scale: 20, //20x the original size
units: 'meters', //everything will be converted to meters in setCoords method
rotation: { x: 90, y: 0, z: 0 }, //default rotation
adjustment: { x: 0, y: 0, z: 0 }, // model center is displaced
feature: geoJsonFeature // a valid GeoJson feature
}
tb.loadObj(options, function (model) {
//this wil position the soldier at the GeoJson feature coordinates
soldier = model.setCoords(feature.geometry.coordinates);
tb.add(soldier);
})
},
render: function (gl, matrix) {
tb.update();
}
});
After the callback is initiated, the object returned will have the following events already
available to listen that enable the UI to behave and react to those.
You can add these addEventListener
lines below to tb.loadObj
:
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
soldier.addEventListener('SelectedChange', onSelectedChange, false);
soldier.addEventListener('Wireframed', onWireframed, false);
soldier.addEventListener('IsPlayingChanged', onIsPlayingChanged, false);
soldier.addEventListener('ObjectDragged', onDraggedObject, false);
soldier.addEventListener('ObjectMouseOver', onObjectMouseOver, false);
soldier.addEventListener('ObjectMouseOut', onObjectMouseOut, false);
tb.add(soldier);
})
In this way you'll be able to manage in you UI through a function once these events are fired.
See below an example for onSelectedChange
to use the method map.flyTo(options[, eventData])
from Mapbox GL:
// method to activate/deactivate a UI button.
// this example uses jQuery
// this example requires a GeoJson feature included in the options of the tb.loadObj(options)
function onSelectedChange(e) {
let selected = e.detail.selected; //we get if the object is selected after the event
$('#deleteButton')[0].disabled = !selected; //we find the delete button with jquery
//if selected
if (selected) {
selectedObject = e.detail; //
//we fly smoothly to the object selected
map.flyTo({
center: selectedObject.userData.feature.properties.camera,
zoom: selectedObject.userData.feature.properties.zoom,
pitch: selectedObject.userData.feature.properties.pitch,
bearing: selectedObject.userData.feature.properties.bearing
});
}
tb.update();
map.repaint = true;
}
Most of the popular 3D formats extensions (.glb, .gltf, .fbx, .dae, ...) are not standard MIME types, so you will need to configure your web server engine to accept this extensions, otherwise you'll receive different HTTP errors downloading them.
If you are using IIS server from an ASP.Net application, add the xml lines below in the </system.webServer>
node of your web.config file:
<system.webServer>
...
<staticContent>
<remove fileExtension=".mtl" />
<mimeMap fileExtension=".mtl" mimeType="model/mtl" />
<remove fileExtension=".obj" />
<mimeMap fileExtension=".obj" mimeType="model/obj" />
<remove fileExtension=".glb" />
<mimeMap fileExtension=".glb" mimeType="model/gltf-binary" />
<remove fileExtension=".gltf" />
<mimeMap fileExtension=".gltf" mimeType="model/gltf+json" />
<remove fileExtension=".fbx" />
<mimeMap fileExtension=".fbx" mimeType="application/octet-stream" />
<remove fileExtension=".dae" />
<mimeMap fileExtension=".dae" mimeType="application/vnd.oipf.dae.svg+xml" />
</staticContent>
</system.webServer>
If you are using ASP.net core server, add the C# lines below in the Configure
method of the Startup
class:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
// Set up custom content types - associating file extension to MIME type
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".mtl"] = "model/mtl";
provider.Mappings[".obj"] = "model/obj";
provider.Mappings[".glb"] = "model/gltf-binary";
provider.Mappings[".gltf"] = "model/gltf+json";
provider.Mappings[".fbx"] = "application/octet-stream";
provider.Mappings[".dae"] = "application/vnd.oipf.dae.svg+xml";
app.UseStaticFiles(new StaticFileOptions
{
ContentTypeProvider = provider
});
...
}
If you are using an nginx server, add the following lines to the nginx.conf file in the http
object:
http {
include /etc/nginx/mime.types;
types {
model/mtl mtl;
model/obj obj;
model/gltf+json gltf;
model/gltf-binary glb;
application/octet-stream fbx;
application/vnd.oipf.dae.svg+xml dae;
}
...
}
If you are using an Apache server, add the following lines to the mime.types file:
model/mtl mtl
model/obj obj
model/gltf+json gltf
model/gltf-binary glb
application/octet-stream fbx
application/vnd.oipf.dae.svg+xml dae
tb.memory() : Object
This will return the member memory
from THREE.WebGLRenderer.info
tb.programs() : int
This will return the lenght of the programs
member from THREE.WebGLRenderer.info
tb.projectToWorld(lnglat) : THREE.Vector3
Calculate the corresponding THREE.Vector3
for a given lnglat
. It's inverse method is tb.unprojectFromWorld
.
tb.queryRenderedFeatures(point) : Array
This methods calculate objects intersecting the picking ray using THREE.Raycaster
and returns an Array of the Threebox objects in the scene ordered by distance from closer to farther away.
Takes an input of {x: number, y: number}
as an object with values representing screen coordinates (as returned by Mapbox GL mouse events as e.point
).
tb.realSunlight([helper = true])
This method creates the an illumination that simulates Sun light for the Threebox scene
. It creates a THREE.HemisphereLight
and one THREE.DirectionalLight
that is positioned based on suncalc.js.
module which calculates the sun position for a given date, time, lng, lat combination. It calls internally to tb.setSunlight
with map.getCenter
and new Date()
as values.
These lights can be overriden manually adding custom lights to the Threebox scene
.
If helper
is true, then a helper is shown.
tb.remove(obj)
Method to remove an object from Threebox scene and the tb.world.children
array.
tb.removeByName(name)
Method to remove an object from Threebox scene and the tb.world.children
array, Searches through an object and its children, starting with the object itself, and removes the first with a matching name..
tb.removeLayer(layerId)
Method to remove a layer from Mapbox, including all 3D objects from Threebox scene and the tb.world.children
array.
tb.setLayerHeigthProperty(layerId, level)
Method to set the height of all the objects in a level.
This method only works if the objects have a GeoJson feature, and a level
attribute among its properties.
tb.setLayerZoomRange(layerId, minZoomLayer, maxZoomLayer)
Custom Layers don't work on minzoom and maxzoom attributes, as every layer is rendering the full scene, and if the layer is including labels they don't hide either on minzoom.
This method sets the zoom range for any custom layer and manages the 3D objects and CSS2D labels toggle action in sync with layer visibility set through tb.setLayoutProperty
.
tb.setLayerZoomVisibility(layerId)
This method sets or resets the layer visibility based on the current zoom. It's used by different methods to set the visibility of the layers.
tb.setLayoutProperty(layerId, name, value)
This method replicates the behaviour of map.setLayoutProperty
when custom layers are affected but it can used for any layer type.
tb.setObjectsScale()
This method scales all the objects from tb.world.children
that are fixedZoom
.
tb.setStyle(styleId[, options])
This method replicates the behaviour of map.setStyle
to remove the 3D objects from tb.world
.
It's a direct passthrough to map.setStyle
but it also calls internally tb.clear(true)
to remove the children from tb.world
and also to dispose all the resources reserved by those objects.
tb.setSunlight(newDate = new Date(), coords)
This method updates Sun light position based on suncalc.js.
module which calculates the sun position for a given date, time, lng, lat combination. It calls internally to tb.setSunlight
with map.getCenter
and new Date()
as values.
tb.toggleLayer(layerId, visible)
This method to toggles any layer visibility but it's specifically designed for custom layers.
If you want to avoid differentiating between Mapbox layers (including custom layers) this method replaces the call to map.setLayoutProperty(layerId, 'visibility', visible)
tb.update()
With tb.loadObj(options, callback(obj))
this is probably the most important method in Threebox
as it's responsible of invoking the THREE.WebGLRenderer.render(scene, camera)
method.
tb.updateLightHelper()
This method updates the poition of tb.lights.dirLightHelper
, it's needed if we want to see the helper properly render when the light moves.
tb.updateSunGround(sunPos)
If tb.realSunlight
is true
, this method updates the light over the satellite style (if applied) according to the sun altitude.
tb.updateSunSky(sunPos)
If tb.sky
is true
, this method updates the sky atmospheric layer with the received sun position.
tb.unprojectFromWorld(Vector3): lnglat
Calculate the corresponding lnglat
for a given THREE.Vector3
. It's inverse method is tb.projectToWorld
.
tb.version() : string
This will return the version of Threebox
In all the samples below, the instance of the Threebox will be always referred as tb
.
tb.altitudeStep : Number
This get/set property receives and returns the size in meters of the step to use when an object is dragged vertically. By default this is set to 0.1 = 10cm.
tb.defaultCursor : string
This get/set property receives and returns the value of the default cursor for the map canvas container this.getCanvasContainer().style.cursor
, initally set to 'default'
.
tb.enableDraggingObjects : Boolean
This get/set property receives and returns the value to enable the option to drag 3D Objects vertical or horizontally created with Threebox.
This property requires tb.enableSelectingFeature
is set to true.
When this property is true, and an object is selected, holding the [Shift] key + mouse click the object will be moved on its x-y axes (horizontally).
Holding the [Ctrl] key + mouse click the object will be moved on its z axis (vertically).
This dragging actions fire ObjectDragged
event when the object is dropped, that can be listened as follows:
obj.addEventListener('ObjectDragged', onDraggedObject, false)
This property doesn't affect to Mapbox fill-extrusion
layers.
tb.enableRotatingObjects : Boolean
This get/set property receives and returns the value to enable the option to drag 3D Objects vertical or horizontally created with Threebox.
This property requires tb.enableSelectingFeature
is set to true.
When this property is true, and an object is selected, holding the [Alt] key + mouse click the object will be rotate pivoting over its anchor on z axis.
Holding the [Ctrl] key + mouse click the object will be moved on its z axis (vertically).
This dragging actions fire ObjectDragged
event when the object is dropped, that can be listened as follows:
obj.addEventListener('ObjectDragged', onDraggedObject, false)
This property doesn't affect to Mapbox fill-extrusion
layers.
tb.enableSelectingFeatures : Boolean
This get/set property receives and returns the value to enable the option to select features from fill-extrusion
layers.
This property doesn't affect to 3D objects.
This selection/unselection actions fire SelectedFeatureChange
event when the object selected or unselected (explicitly or implicitly because of other feature is selected instead), and can be listened as follows:
obj.addEventListener('SelectedFeatureChange', onSelectedFeatureChange, false)
tb.enableSelectingObjects : Boolean
This get/set property receives and returns the value to enable the option to select 3D Objects created with Threebox.
This selection/unselection actions fire SelectedChange
event when the object selected or unselected (explicitly or implicitly because of other object is selected instead), and can be listened as follows:
obj.addEventListener('SelectedChange', onSelectedChange, false)
This property doesn't affect to Mapbox fill-extrusion
layers.
tb.enableTooltips : Boolean
This get/set property receives and returns the value to enable the option to have tooltips (custom or by default) on objects.
This property requires tb.enableSelectingFeature
is set to true.
When this property is true, and an object is overed or selected, its tooltip will be shown.
tb.fov : Number (degrees)
By default is ThreeboxConstants.FOV_DEGREES
.
This get/set property sets and returns the value of the Field of View (FOV) used in the Camera.
This value is only valid when tb.orthographic
is false which implicitly means the camera being used is a THREE.PerspectiveCamera
.
When tb.orthographic
is true, this value has no effect because the FOV for orthographic view is always 0.
IMPORTANT
This property accepts values between 0 and 60 (that's the maximum range of FOV by Mapbox), but below 2.5 degrees will generate serious issues with polygons in fill-extrusions and 3D meshes, and above 45 degrees will also produce clipping and performance issues that can freeze your map.
Mapbox minimum value for the FOV cannot be 0
, so if it receives a 0
value, it will be converted to 0.01
by Mapbox map.transform.fov
property to it's minimum value.
tb.gridStep : Number(integer)
This get/set property receives and returns the size in precision decimals of the step to use when an object is dragged horizontally reducing the number of decimals managed by Mapbox in its coords.
By default the precision of this step is set to 6 decimals = 11.1 cm, setting this property to 7 the grid will be reduced to 1.1 cm.
Mapbox minimum value for the FOV is 0.01
, so if it receives a 0
value, it will be converted to 0.01
by Mapbox map.transform.fov
property to it's minimum value.
tb.lights : Object
This get\set property receives and returns the full set of lights applied to the scene.
tb.lights.ambientLight
is initialized with an instance THREE.AmbientLight
by tb.defaultLights()
method, but can be overriden manually.
tb.lights.dirLight
could be initialized with an instance THREE.DirectionalLight
by tb.defaultLights()
or tb.setSunlight
. It's not recommended to override this light is using realSunlight
property.
tb.lights.dirLightBack
is initialized with an instance THREE.DirectionalLight
by tb.defaultLights()
method, but can be overriden manually.
tb.lights.dirLightHelper
is initialized with an instance THREE.DirectionalLightHelper
by tb.setSunlight
. I'll be visible only if realSunlightHelper
is tru in Threebox constructor.
tb.lights.hemiLight
is initialized with an instance THREE.HemisphereLight
by tb.setSunlight
.
tb.lights.pointLight
is not initialized by default.
tb.multiLayer : Boolean
By default is false
.
This get/set property receives and returns the value to enable the option to have multiple 3D layers, where a default layer will be created internally that will manage the tb.update
calls
Despite this value can be changed in runtime, the value won't take effect unless there's a style change through tb.setStyle
. So if you know your page could have multiple 3D layers, it's recommended to initialize it to true in Threeboc constructor with the init param multiLayer: true
.
tb.orthographic : Boolean
By default is false
.
This get/set property sets and returns the value of the Camera to be used.
When tb.orthographic
is true
, the camera being used will be an instance of THREE.OrthographicCamera
.
If tb.orthographic
is false
, the camera being used will be an instance of THREE.PerspectiveCamera
.
IMPORTANT
Pure orthographic view is not supported by Mapbox, as the minimum value for FOV is 0.01
, so iftb.orthographic
is true
will generate serious issues with polygons and depth calculations with fill-extrusions.
Don't set this property to true
is you are creating fill-extrusion layers. If need to have at the same time fill-extrusions and 3D Objects at the same time but want to keep an orthographic-like camera, the recommendation is to use tb.orthographic = false
and tb.fov = 2.5
.
tb.rotationStep : Number
This get/set property receives and returns the size in degrees of the step to use when an object is dragged and rotated. By default this is set to 5.
tb.sky: Boolean
By default is false
. This property is set by the init param sky: true
in threebox constructor.
This get/set property sets and returns the option to have a built-in atmospheric layer initially set with the time and the map center position.
This layer is automatically updated if realSunlight
is also true, but it can be updated separately through tb.updateSunSky(tb.getSunSky())
method call.
If this property is set to false
after the atmospheric sky layer is created, it will remove the layer.
tb.terrain: Boolean
By default is false
. This property is set by the init param terrain: true
in threebox constructor.
This get/set property sets and returns the option to have a built-in terrain layer.
This layer is automatically updated if realSunlight
is also true, adjusting it's light but it can be updated separately through tb.updateSunGround(tb.getSunPosition())
method call.
If this property is set to false
after the terrain layer is created, it will remove the layer.
Threebox offers convenience functions to construct meshes of various Three.js meshes, as well as 3D models. Under the hood, they invoke a subclass of THREE.Object3D.
Objects in Threebox fall under two broad varieties. Static objects don't move or change once they're placed, and used usually to display background or geographical features. They may have complex internal geometry, which are expressed primarily in lnglat coordinates.
In contrast, dynamic objects can move around the map, positioned by a single lnglat point. Their internal geometries are produced mainly in local scene units, whether through external obj files, or these convenience methods below.
tb.line(options);
Adds a line to the map, in full 3D space. Color renders independently of scene lighting. Internally, calls a custom line shader.
option | required | default | type | purpose |
---|---|---|---|---|
geometry |
yes | NA | lineGeometry | Array of lnglat coordinates to draw the line |
color |
no | black | color | Color of line. Unlike other Threebox objects, this color will render on screen precisely as specified, regardless of scene lighting |
width |
no | 1 | number | Line width. Unlike other Threebox objects, this width is in units of display pixels, rather than meters or scene units. |
opacity |
no | 1 | Number | Line opacity |
tb.extrusion(options);
Add a extruded shape to the map. Internally, calls THREE.ExtrudeBufferGeometry
, and also to Object3D(options)
to convert it in a dynamic object.
option | required | default | type | description |
---|---|---|---|---|
coordinates |
no | [[[]]] or Vector2 array | nested array | Nested array following the standard of a geoJson feature.geometry.coordinates with type polygon, or a THREE.Vector2 array. |
geometryOptions |
no | {} | Object | Object that contains the options following ExtrudeGeometry |
height |
no | 100 | Number | Length of the extruded shape. |
units |
no | scene |
string ("scene" or "meters") | Units with which to interpret the object's vertices. If meters, Threebox will also rescale the object with changes in latitude, to appear to scale with objects and geography nearby. |
scale |
no | 1 | number or {x, y, z} | Scale of the object along the three axes, to size it appropriately before future transformations. Note that future scaling applies atop this transformation, rather than overwriting it. scale attribute must be provided in number or per axis ((i.e. for an object transformed to 3 times higher than it's default size scale: {x: 1, y: 1, z: 3} |
rotation |
no | 0 | number or {x, y, z} | Rotation of the object along the three axes, to align it to desired orientation before future rotations. Note that future rotations apply atop this transformation, and do not overwrite it. rotate attribute must be provided in number or per axis ((i.e. for an object rotated 90 degrees over the x axis rotation: {x: 90, y: 0, z: 0} |
materials |
no | THREE.MeshPhongMaterial({ color: 0x660000, side: THREE.DoubleSide }) |
threeMaterial or threeMaterials array | THREE material to use. Can be invoked with a text string, or a predefined material object via THREE itself. |
anchor |
no | bottom-left |
string | This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top , bottom , left , right , center , top-left , top-right , bottom-left , bottom-right . Default value is bottom-left |
adjustment |
no | 1 | {x, y, z} | For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglat on 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level. |
tooltip |
no | false | bool | This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips |
bbox |
no | false | bool | This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects |
raycasted |
no | true | bool | This param allows to hide an object from raycast individually |
tb.label(options);
Creates a new HTML Label object that can be positioned through obj.setCoords(coords)
and then added to Threebox scene through tb.add(obj)
.
Internally this method uses a CSS2DObject
rendered by THREE.CSS2DRenderer
to create an instance of THREE.CSS2DObject
that will be associated to the obj.label
property.
option | required | default | type | description |
---|---|---|---|---|
htmlElement |
yes | null | htmlElement | HTMLElement that will be rendered as a CSS2DObject |
cssClass |
no | " label3D" | string | CssClass that will be aggregated to manage the styles of the label object. |
alwaysVisible |
no | false | number | Number of width and height segments. The higher the number, the smoother the sphere. |
topMargin |
no | -0.5 | int | If topMargin is defined in number, it will be added to it's vertical position in units, where 1 is the object height. By default a label will be positioned in the vertical middle of the object (topMargin: -0.5 ) |
feature |
no | null | GeoJson feature | GeoJson feature to assign to the tooltip. It'll be used for dynamic positioning |
tb.Object3D(options)
Add any geometry as THREE.Object3D
or THREE.Mesh
instantiated elsewhere in Three.js, to empower it with Threebox methods below. Unnecessary for 3d models instantiated with tb.loadObj
above.
option | required | default | type | description |
---|---|---|---|---|
obj |
yes | null | THREE.Mesh |
Object to be enriched with this method adding new attributes. |
units |
no | scene |
string ("scene" or "meters") | Units with which to interpret the object's vertices. If meters, Threebox will also rescale the object with changes in latitude, to appear to scale with objects and geography nearby. |
anchor |
no | bottom-left |
string | This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top , bottom , left , right , center , top-left , top-right , bottom-left , bottom-right . Default value is bottom-left |
adjustment |
no | 1 | {x, y, z} | For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglat on 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level. |
tooltip |
no | false | bool | This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips |
bbox |
no | false | bool | This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects |
raycasted |
no | true | bool | This param allows to hide an object from raycast individually |
This method enriches the Object in the same way is done at 3D Models through tb.loadObj
.
tb.sphere(options);
Add a sphere to the map. Internally, calls THREE.Mesh
with a THREE.SphereGeometry
, and also to Object3D(options)
to convert it in a dynamic object.
option | required | default | type | description |
---|---|---|---|---|
radius |
no | 50 | number | Radius of sphere. |
units |
no | scene |
string ("scene" or "meters") | Units with which to interpret the object's vertices. If meters, Threebox will also rescale the object with changes in latitude, to appear to scale with objects and geography nearby. |
sides |
no | 8 | number | Number of width and height segments. The higher the number, the smoother the sphere. |
color |
no | black | color | Color of sphere. |
material |
no | MeshLambertMaterial | threeMaterial | THREE material to use. Can be invoked with a text string, or a predefined material object via THREE itself. |
anchor |
no | bottom-left |
string | This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top , bottom , left , right , center , top-left , top-right , bottom-left , bottom-right . Default value is bottom-left |
adjustment |
no | 1 | {x, y, z} | For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglat on 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level. |
tooltip |
no | false | bool | This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips |
bbox |
no | false | bool | This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects |
raycasted |
no | true | bool | This param allows to hide an object from raycast individually |
tb.tooltip(options);
Creates a new browser-like Tooltip object that can be positioned through obj.setCoords(coords)
and then added to Threebox scene through tb.add(obj)
.
Internally this method uses a CSS2DObject
rendered by THREE.CSS2DRenderer
to create an instance of THREE.CSS2DObject
that will be associated to the obj.tooltip
property.
option | required | default | type | description |
---|---|---|---|---|
text |
yes | "" | string | String that will be used to rendered as a CSS2DObject |
cssClass |
no | "toolTip text-xs" | string | CssClass that will be aggregated to manage the styles of the label object. |
mapboxStyle |
no | false | int | If mapboxStyle is true, it applies the same styles the Mapbox GL popups. |
topMargin |
no | 0 | int | If topMargin is defined in number, it will be added to it's vertical position in units, where 1 is the object height. By default a label will be positioned on top of the object (topMargin: 0 ) |
feature |
no | null | GeoJson feature | GeoJson feature to assign to the tooltip. It'll be used for dynamic positioning |
tb.tube(options);
Extrude a tube along a specific lineGeometry, with an equilateral polygon as cross section. Internally uses a custom tube geometry generator, and also to Object3D(options)
to convert it in a dynamic object.
option | required | default | type | description |
---|---|---|---|---|
geometry |
yes | NA | lineGeometry | Line coordinates forming the tube backbone |
radius |
no | 20 | number | Radius of the tube cross section, or half of tube width. |
sides |
no | 8 | number | Number of facets along the tube. The higher, the more closely the tube will approximate a smooth cylinder. |
material |
no | MeshLambertMaterial | threeMaterial | THREE material to use. Can be invoked with a text string, or a predefined material object via THREE itself. |
color |
no | black | color | Tube color. Ignored if material is a predefined THREE.Material object. |
opacity |
no | 1 | Number | Tube opacity |
anchor |
no | bottom-left |
string | This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top , bottom , left , right , center , top-left , top-right , bottom-left , bottom-right . Default value is bottom-left |
adjustment |
no | 1 | {x, y, z} | For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglat on 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level. |
tooltip |
no | false | bool | This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips |
bbox |
no | false | bool | This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects |
raycasted |
no | true | bool | This param allows to hide an object from raycast individually |
In all the samples below, the instance of the Threebox object will be always referred as obj
obj.addCSS2D(element, objName [, center = obj.anchor, height = 0])
This is a generic method that uses the DOM HTMLElement received to paint it on screen in a relative position to the object that contains it.
objName
is needed to name the object and potentially to remove a previous one.
center
defines the position where the label will rendered, by default the object anchor obj.anchor
.
height
defines this object position, where 0 is the object bottom and 1 is the object top, by default the bottom-center (0) of the object.
Internally this method uses a CSS2DObject
rendered by THREE.CSS2DRenderer
to create an instance of THREE.CSS2DObject
that is returned.
obj.addHelp(helpText [,objName = helpName, mapboxStyle = false, center = obj.anchor, height = 0])
This method creates a browser-like help tooltip instance that is accessible through obj.help
.
This help tooltip is only visible when an object is being dragged for a translation, rotation or altitude change.
If mapboxStyle
is true, it applies the same styles the Mapbox GL popups.
center
defines the position where the label will rendered, by default the object anchor obj.anchor
.
height
defines this object position, where 0 is the object bottom and 1 is the object top, by default the bottom-center (0) of the object.
Internally this method uses a CSS2DObject
rendered by THREE.CSS2DRenderer
to create an instance of THREE.CSS2DObject
that will be associated to the obj.help
property.
Internally this method calls objects.prototype.drawTooltip
to create the needed HTML to wrap up the HTMLElement
received by param.
Internally this method calls obj.addCSS2D
.
obj.addLabel(HTMLElement [, visible, center = obj.anchor, height = 0.5])
It uses the DOM HTMLElement received to paint it on screen in a relative position to the object that contains it.
If visible
is true, the label will be always visible, otherwise by default its value is false and it's regular behavior is only to be shown on MouseOver.
center
defines the position where the label will rendered, by default the object anchor obj.anchor
.
height
defines this object position, where 0 is the object bottom and 1 is the object top, by default the middle-center (0.5) of the object.
Internally this method uses a CSS2DObject
rendered by THREE.CSS2DRenderer
to create an instance of THREE.CSS2DObject
that will be associated to the obj.label
property.
Internally this method calls obj.drawLabelHTML
to create the needed HTML to wrap up the HTMLElement
received by param.
obj.addTooltip(tooltipText [, mapboxStyle = false, center = obj.anchor, custom = true, height = 1])
This method creates a browser-like tooltip for the object using the tooltipText.
If mapboxStyle
is true, it applies the same styles the Mapbox GL popups.
center
defines the position where the label will rendered, by default the object anchor obj.anchor
.
custom
is always true for explicitly added tooltips by the user, unless the tooltip is automatically generated by Threebox.
height
defines this object position, where 0 is the object bottom and 1 is the object top, by default the top-center (1) of the object.
Internally this method uses a CSS2DObject
rendered by THREE.CSS2DRenderer
to create an instance of THREE.CSS2DObject
that will be associated to the obj.tooptip
property.
Internally this method calls obj.addHelp
.
obj.copyAnchor(anchor)
Copies the anchor properties, internally used in obj.duplicate
.
obj.drawBoundingBox
This method creates two bounding boxes using THREE.Box3Helper
The first bounding box will be assigned to obj.boundingBox
property and the second will be assigned to obj.boundingBoxShadow
.
obj.drawLabelHTML(HTMLElement [, visible = false, center = obj.anchor])
It uses the DOM HTMLElement received to paint it on screen in a relative position to the object that contains it.
If visible
is true, the label will be always visible, otherwise by default its value is false and it's regular behavior is only to be shown on MouseOver.
center
defines the object center of position and rotation that in 3D objects is defined through options.adjustment
param. As the label is
calculated based on the center of the object, this value will change the position of the object.
Its position is always relative to the object that contains it and rerendered whenever that label is visible.
Internally this method uses a CSS2DObject
rendered by THREE.CSS2DRenderer
to create an instance of THREE.CSS2DObject
that will be associated to the obj.label
property.
obj.duplicate()
Returns a clone of the object. Improves around a 95% the performance when handling many identical objects, by reusing materials and geometries.
obj.removeCSS2D(objName)
Removes the instance of CSS2DObject
by objName
and dispose its resources.
obj.removeHelp()
Removes the instance of CSS2DObject
stored in obj.help
.
Internally it calls obj.removeCSS2D
method.
obj.removeLabel()
Removes the instance of CSS2DObject
stored in obj.label
.
Internally it calls obj.removeCSS2D
method.
obj.removeTooltip()
Removes the instance of CSS2DObject
stored in obj.tooltip
.
Internally it calls obj.removeCSS2D
method.
obj.set(options)
Broad method to update object's position, rotation, and scale in only one call. Internally it calls to obj._setObject(options)
method.
This method can also be used to animate an object if options.duration
has a value.
Check out the Threebox Types section below for details.
options object on animations (duration > 0
)
option | required | default | type | description |
---|---|---|---|---|
coords |
no | NA | lnglat |
Position to which to move the object |
rotation |
no | NA | rotationTransform |
Rotation(s) to set the object, in units of degrees |
scale |
no | NA | scaleTransform |
Scale(s) to set the object, where 1 is the default scale |
duration |
no | 1000 | number | Duration of the animation, in milliseconds to complete the values specified in the other properties scale , rotation and coords . If 0 or undefined it will apply the values to the object directly with no animation. |
options object without animations (duration == 0
)
option | required | default | type | description |
---|---|---|---|---|
position |
no | NA | lnglat |
Position to which to move the object |
rotation |
no | NA | rotationTransform |
Rotation(s) to set the object, in units of degrees |
scale |
no | NA | scaleTransform |
Scale(s) to set the object, where 1 is the default scale |
worldCoordinates |
no | NA | Vector3 |
Duration of the animation, in milliseconds to complete the values specified in the other properties scale , rotation and coords . If 0 or undefined it will apply the values to the object directly with no animation. |
quaternion |
no | NA | [Vector3 , radians ] |
Rotation(s) to set to the axes received by the Vector3 and in by the angle in radians |
translate |
no | NA | lnglat |
Increment to the coords position to translate the object. |
worldTranslate |
no | NA | Vector3 |
Increment to the object world position to translate the object. |
obj.setAnchor(anchor)
Sets the positional and pivotal anchor automatically from string param. Calculates dynamically the positional and pivotal anchor.
anchor
is a string value that could have the following values: top
, bottom
, left
, right
, center
, top-left
, top-right
, bottom-left
, bottom-right
.
Default value is bottom-left
for precison on positioning
obj.setBoundingBoxShadowFloor()
This method is called from obj.setCoords
every time an object receives new coords to position obj.boundingBoxShadow
at the height of the floor.
So in this way if an object changes it's height the shadow box always projects over the floor and it's easier to visualize, position and rotate dragging it.
obj.setCoords(lnglat)
Positions the object at the defined lnglat
coordinates, and resizes it appropriately if it was instantiated with units: "meters"
.
Can be called before adding object to the map.
obj.setFixedZoom(scale)
Sets the scale used to convert the object based on fixedZoom
value. The received param scale
should be always equal to map.transform.scale
.
This method is called from obj.setScale
and other loading methods, so it's not needed to be called separately from the UI.
obj.setObjectScale(scale)
Sets the scale used to convert the object considering object current obj.unitsPerMeter
and depending the object is in units scene
or meters
.
The received param scale
should be always equal to map.transform.scale
.
This method calls internally obj.setScale(scale)
, obj.setBoundingBoxShadowFloor()
, obj.setReceiveShadowFloor()
sequentially.
obj.setRotation(xyz)
Rotates the object over its defined center in the 3 axes, the value must be provided in degrees and could be a number (it will apply the rotation to the 3 axes) or as an {x, y, z} object. This rotation is applied on top of the rotation provided through loadObj(options).
obj.setRotationAxis(xyz)
Rotates the object over one of its bottom corners on z axis, the value must be provided in degrees and could be a number (it will apply the rotation to the 3 axes) or as an {x, y, z} object. This rotation is applied on top of the rotation provided through loadObj(options).
obj.setScale(scale)
Sets the scale used to convert the object considering object current obj.unitsPerMeter
and depending the object is in units scene
or meters
.
The received param scale
should be always equal to map.transform.scale
, if it's null, obj.userData.mapScale
will be use instead.
This method calls internally obj.setFixedZoom
.
obj.setTranslate(lnglat)
Movesthe object from it's current position adding the lnglat
coordinates recibed. Don't confuse this method with obj.setCoords
This method must be called after adding object to the map.
In all the samples below, the instance of the Threebox object will be always referred as obj
.
obj.boundingBox : THREE.Box3Helper
This get/set property receives and returns a THREE.Box3Helper
which contains the object in it's initial size.
boundingBox
represents is visible once the object is on MouseOver (yellow) or Selected (green).
By Threebox design .boundingBox
is hidden for THREE.Raycaster
even when it's visible for the camera.
TODO: In next versions of Threebox, this object material will be configurable. In this versión still predefined in Objects.prototype
obj.boundingBoxShadow : THREE.Box3Helper
This get/set property receives and returns a THREE.Box3Helper
which contains the object in it's initial size but 0 height and projected to the floor of the map independently of its heigh position, so it acts as a shadow of the shape.
boundingBoxShadow
represents is visible once the object is on MouseOver or Selected in black color.
By Threebox design .boundingBoxShadow
is hidden for THREE.Raycaster
even when it's visible for the camera.
TODO: In next versions of Threebox, this object material will be configurable. In this versión still predefined in Objects.prototype
obj.castShadow : boolean
This get/set property receives and returns the value of the option of objects to cast a shadow.
It creates a plane with a THREE.PlaneBufferGeometry
and a THREE.ShadowMaterial()
centered on the object to project the shadow with the size of the longest dimension (x, y, z) size of the object and make it 10 times bigger to be able to hold the full shadow.
obj.color : integer hex
This get/set property receives and returns the value of the color from a hexadecimal value.
This method calls color.setHex
obj.help : CSS2DObject
This get property returns a CSS2DObject
THREE.CSS2DObject
value that represents the help tooltip of a THREE.Object3D
created by obj.addHelp
method, where the value of a rotation, translation or altitude change is shown while dragging. Despite this is accessible, this is an internal object only visible on drag&drop actions over an object.
hidden
obj.hidden : boolean
This get/set property receives and returns the value of the hidden status of an object. This property overrides the value of obj.visibility
.
obj.fixedZoom : Number
This get/set property receives and returns the value for the zoom below the one the object will have a fixed scale at any zoom level. Over the value, the object will rescale as always.
This property is very useful for models that need to be visible on very low zoom levels (i.e. an airplane describing a world route), but they also need to be visible when zoom is higher.
It's important to know that fixedZoom
will use the model in scene
units, not in meters
.
obj.label : CSS2DObject
This get property returns a CSS2DObject
THREE.CSS2DObject
value that represents the label of a THREE.Object3D
created by obj.addLabel
method. The label could be used as an element to show on mouse over or to be always visible. It's normally used to show attributes or status of a threebox object and can contain any HTMLElement.
obj.modelHeight : Number
This get property returns the height of the object in meters.
obj.raycasted : boolean
This get/set property receives and returns a boolean value to hide a THREE.Object3D
from THREE.Raycaster
if false.
By default all the objects are visible for raycaster. This value can be initialized by default through tb.loadObj
or tb.Object3D
.
obj.receiveShadow : boolean
This get/set property receives and returns the value of the option of objects to receive a shadow.
obj.tooltip : CSS2DObject
This get property returns a CSS2DObject
THREE.CSS2DObject
value that represents the tooltip of a THREE.Object3D
created by obj.addTooltip
method.
The tooltip by default shows the uuid
value of a threebox object and it's only visible if tb.enableTooltips
is true.
obj.unitsPerMeter : Number
This get property returns the conversion value of units per meter at the object current latitude.
obj.visibility : boolean
This get/set property receives and returns a boolean value to override the property visible
of a THREE.Object3D
,
adding also the same visibility value for obj.label
and obj.tooltip
This property is overriden by obj.hidden
, so if obj.hidden
is false, obj.visibility
is ignored.
By Threebox design .boundingBoxShadow
is hidden for THREE.Raycaster
even when it's visible for the camera.
obj.wireframe : boolean
This get/set property receives and returns a boolean value to convert an THREE.Object3D
in wireframes or texture it.
By Threebox design whenever an object is converted to wireframes, it's also hidden for THREE.Raycaster
even when it's visible for the camera.
In all the samples below, the instance of the Threebox object will be always referred as obj
obj.addEventListener('IsPlayingChanged', onIsPlayingChanged, false)
This event is fired once an object changes its animation playing status, it means it will be fired both when an object animation starts and stops to play.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
.
map.addLayer({
...
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
soldier.addEventListener('IsPlayingChanged', onIsPlayingChanged, false);
tb.add(soldier);
})
...
});
...
function onIsPlayingChanged(eventArgs) {
if (e.detail.isPlaying) {
//do something in the UI such as changing a button state
}
else {
//do something in the UI such as changing a button state
}
}
obj.addEventListener('ObjectChanged', onObjectChanged, false)
This event is fired when an object is changed by any method, including animations.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
, and the action made to the object that cound be one or more of the following:
position
: defined as lnglat + alt coords (i.e.[-122.43471544901193, 37.73719686062993, 0]
),undefined
if the change doesn't affect position.rotation
: defined as radians in Vector3 format (i.e.{x: 0, y: 0, z: -3.026900303641103}
),undefined
if the change doesn't affect rotation.scale
: defined as a Vector3 (i.e.{x: 1, y: 1, z: 1}
), ,undefined
if the change doesn't affect scale.
map.addLayer({
...
tb.loadObj(options, function (model) {
model.setCoords(origin);
model.addEventListener('ObjectChanged', onObjectChanged, false);
tb.add(model);
})
...
});
...
function onObjectChanged(e) {
let object = e.detail.object; // the object that has changed
let action = e.detail.action; // the action that defines the change
//do something in the UI such as changing a button state or updating the new position and rotation
}
obj.addEventListener('ObjectDragged', onDraggedObject, false)
This event is fired when an object changes is dragged and dropped in a different position, and only once when map.once('mouseup'
and map.once('mouseout'
.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
, and the action made during the dragging that cound be "rotate"
if the object has been rotated on its center axis or "translate"
/"altitude"
if the object has been moved to other position .
map.addLayer({
...
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
soldier.addEventListener('ObjectDragged', onDraggedObject, false);
tb.add(soldier);
})
...
});
...
function onDraggedObject(e) {
let draggedObject = e.detail.draggedObject; // the object dragged
let draggedAction = e.detail.draggedAction; // the action during dragging
//do something in the UI such as changing a button state or updating the new position and rotation
}
obj.addEventListener('ObjectMouseOver', onObjectMouseOver, false)
This event is fired when an object is overed by the mouse pointer.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
.
map.addLayer({
...
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
soldier.addEventListener('ObjectMouseOver', onObjectMouseOver, false);
tb.add(soldier);
})
...
});
...
function onObjectMouseOver(e) {
//do something in the UI such as adding help or showing this object attributes
}
obj.addEventListener('ObjectMouseOut', onObjectMouseOut, false)
This event is fired when the mouse pointer leaves an object that has been overed.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
.
map.addLayer({
...
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
soldier.addEventListener('ObjectMouseOut', onObjectMouseOut, false);
tb.add(soldier);
})
...
});
...
function onObjectMouseOut(e) {
//do something in the UI such as removing help
}
obj.addEventListener('SelectedChange', onSelectedChange, false)
This event is fired once an object changes its selection status, it means it will be fired both when an object is selected or unselected.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
.
map.addLayer({
...
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
soldier.addEventListener('SelectedChange', onSelectedChange, false);
tb.add(soldier);
})
...
});
...
function onSelectedChange(e) {
let selectedObject = e.detail; //we get the object selected/unselected
let selectedValue = selectedObject.selected; //we get if the object is selected after the event
}
map.on('SelectedFeature', onSelectedFeature)
This event is fired by Threebox usign the same pattern of mapbox the feature-state
select
and hover
TODO
once an object changes its selection status, it means it will be fired both when an object is selected or unselected.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
.
map.addLayer({
'id': 'room-extrusion',
'type': 'fill-extrusion',
'source': 'floorplan',
'paint': {
// See the Mapbox Style Specification for details on data expressions.
// https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions
// Get the fill-extrusion-color from the source 'color' property.
'fill-extrusion-color':
[
'case',
['boolean', ['feature-state', 'select'], false],
'#ffff00',
['boolean', ['feature-state', 'hover'], false],
'#0000ff',
['get', 'color']
],
// Get fill-extrusion-height from the source 'height' property.
'fill-extrusion-height': ['get', 'height'],
// Get fill-extrusion-base from the source 'base_height' property.
'fill-extrusion-base': ['get', 'base_height'],
// Make extrusions slightly opaque for see through indoor walls.
'fill-extrusion-opacity': 0.5
}
});
//selected extrusion feature event
map.on('SelectedFeature', onSelectedFeature);
...
function onSelectedFeature(e) {
let selectedObject = e.detail; //we get the object selected/unselected
let selectedValue = selectedObject.selected; //we get if the object is selected after the event
}
obj.addEventListener('Wireframed', onWireframed, false)
This event is fired once an object is changes its wireframe status, it means it will be fired both when an object is wireframed or textured again.
The event can be listened at any time once the tb.loadObj
callback method is being executed.
An instance of the object that changes is returned in eventArgs.detail
.
map.addLayer({
...
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
soldier.addEventListener('Wireframed', onWireframed, false);
tb.add(soldier);
})
...
});
...
function onWireframed(e) {
if (e.detail.wireframe) {
//do something in the UI such as changing a button state
}
else {
//do something in the UI such as changing a button state
}
}
obj.playDefault(options)
Plays the default embedded animation of a loaded 3D model.
options object
option | required | default | type | description |
---|---|---|---|---|
duration |
no | 1000 | number | Duration of the animation, in milliseconds |
speed |
no | 1 | number | This value changes the obj.mixer.timeScale of the animation being played where 1 is the default duration of the animation, < 1 will mathe the animation slower and > 1 will make the animation faster |
obj.playAnimation(options)
Plays one of the embedded animations of a loaded 3D model. The animation index must be set in the attribute options.animation
options object
option | required | default | type | description |
---|---|---|---|---|
animation |
yes | NA | number | Index of the animation in the 3D model. If you need to check whats the index of the animation you can get the full array using obj.animations . |
duration |
no | 1000 | number | Duration of the animation, in milliseconds |
speed |
no | 1 | number | This value changes the obj.mixer.timeScale of the animation being played where 1 is the default duration of the animation, < 1 will mathe the animation slower and > 1 will make the animation faster |
obj.followPath(options [, callback] )
Translate object along a specified path. Optional callback function to execute when animation finishes
option | required | default | type | description |
---|---|---|---|---|
path |
yes | NA | lineGeometry | Path for the object to follow |
duration |
no | 1000 | number | Duration to travel the path, in milliseconds |
trackHeading |
no | true | boolean | Rotate the object so that it stays aligned with the direction of travel, throughout the animation |
obj.stop()
Stops all of object's current animations.
[longitude, latitude(, meters altitude)]
An array of 2-3 numbers representing longitude, latitude, and optionally altitude (in meters). When altitude is omitted, it is assumed to be 0. When populating this from a GeoJson Point, this array can be accessed at point.geometry.coordinates
.
While altitude is not standardized in the GeoJson specification, Threebox will accept it as such to position objects along the z-axis.
[pointGeometry, pointGeometry ... pointGeometry]
An array of at least two lnglat's, forming a line. When populating this from a GeoJson Linestring, this array can be accessed at linestring.geometry.coordinates
.
number
or {x: number, y: number, z: number}
Angle(s) in degrees to rotate object. Can be expressed as either an object or number.
The object form takes three optional parameters along the three major axes: x is parallel to the equator, y parallel to longitudinal lines, and z perpendicular to the ground plane.
The number form rotates along the z axis, and equivalent to {z: number}
.
number
or {x: number, y: number, z: number}
Amount to scale the object, where 1 is the default size. Can be expressed as either an object or number.
The three axes are identical to those of rotationTransform
. However, expressing as number form scales all three axes by that amount.
string
or instance of THREE.Material()
Denotes the material used for an object. This can usually be customized further with color
and opacity
parameters in the same
Can be expressed as a string to the corresponding material type (e.g. "MeshPhysicalMaterial"
for THREE.MeshPhysicalMaterial()
), or a prebuilt THREE material directly.
- Use
obj.duplicate()
when adding many identical objects. If your object contains other objects not in theobj.children
collection, then those objects need to be cloned too. - This is a by default behavior when
tb.loadObj
is called.