Can anyone help me understand how I need to structure my code for this mapbox w/ threebox project in Angular?
I can't figure out why this code:
this.tb.loadObj(options, function (model) {
var house = model.setCoords(origin);
this.tb.add(house);
});
is throwing the following error:
ERROR Error: Uncaught (in promise): ReferenceError: tb is not defined ReferenceError: tb is not defined
Even after seeming to recognize tb
as defined when I run console.log statements within this code block. But then this error shows up right afterwards and my 3D model never loads.
Here is the full code for the component, any advice on how to solve this issue would be appreciated:
import { Component, OnInit } from '@angular/core';
import { environment } from '../../../environments/environment';
import {Threebox} from 'threebox-plugin';
import * as M from 'mapbox-gl';
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
/// default settings
long = -122.4192;
lat = 37.7793;
map: M.Map;
style = 'mapbox://styles/mapbox/light-v10';
// data
source: any;
markers: any;
// render
tb: Threebox;
constructor() { }
ngOnInit(): void {
(M as any).accessToken = environment.mapbox.accessToken;
this.buildMap();
this.map.on('style.load', this.onLoad.bind(this));
this.map.on('load', (event) => {
/// register source
this.map.addSource('localdata', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [this.long, this.lat]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
}]
}
});
/// get source
this.source = this.map.getSource('localdata')
// markers
this.source._data.features.forEach((marker) => {
var lng = marker['geometry']['coordinates'][0]
var lat = marker['geometry']['coordinates'][1]
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
// make a marker for each feature and add to the map
new M.Marker({color: 'black'})
.setLngLat([lng, lat])
.addTo(this.map);
});
});
// Add map controls
this.map.addControl(new M.NavigationControl());
this.map.on('mousemove', function (e) {
document.getElementById('info').innerHTML =
// e.point is the x, y coordinates of the mousemove event relative
// to the top-left corner of the map
// e.lngLat is the longitude, latitude geographical position of the event
e.lngLat.lat.toFixed(6) + ', ' + e.lngLat.lng.toFixed(6) ;
});
};
// functions
buildMap() {
this.map = new M.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
zoom: 18,
center: [this.long, this.lat],
pitch: 60,
});
}
onLoad(){
this.map.addLayer({
id: 'house',
type: 'custom',
// renderingMode: '3d',
onAdd(map, mbxContext) {
this.tb = new Threebox(
map,
mbxContext,
{ defaultLights: true }
);
//starting location for both map and eventual sphere
var origin = [this.long, this.lat];
var options = {
// obj: 'src/assets/3d/house.gltf',
obj: 'https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf',
type: 'gltf',
scale: 1,
units: 'meters',
rotation: { x: 90, y: 0, z: 0 } //default rotation
}
this.tb.loadObj(options, function (model) {
var house = model.setCoords(origin);
this.tb.add(house);
});
},
render: function (gl, matrix) {
this.tb.update();
}
});
};
}
It seems as window.tb solves that issue.
Initialise tb outside onAdd function.
Now you can use either this.tb or window.tb because both are the same.