I am working with the rendering of Mapbox in Angular framework. Right now the issue what am facing is that I cannot load the map in the browser.
I have defined a function where I've given all the required to load the map and I am calling the function from an HTML div container after validating a condition. The control goes into the function but the error is that it is not identifying the container property of the map.
My HTML code:
<div id="map" style="margin-top: 370px;" *ngIf="result;then loadMap()">
my script:
loadMap(){
this.map=new Map({
container:document.getElementById('map') ,//'map'
style: 'mapbox://styles/mapbox/streets-v11',
center: { lng: -102.380979, lat: 35.877742 },
zoom: 9,
pitch: 20,
attributionControl: false
});
this.map.addControl(
new NavigationControl({
showZoom: true,
showCompass: true
}),
'bottom-right'
);
}
The error that I am facing:
Error: Invalid type: 'container must be a String or HTMLElement.
Error
Also, is it really possible to load map with a function call or am I just wasting my time here?
This is what i've been doing.I cannot give upon ngAfterViewInit because it is required for initialization purpose of the DOM.
export class DashboardComponent implements OnChanges,OnDestroy,AfterViewInit {
#Input() searchResults:SidenavComponent;
private map: Map;
constructor(){ }
ngOnChanges(changes:SimpleChanges){
if(!changes.searchResults){
console.log("Inside if");
console.log(changes.searchResults)
this.ngAfterViewInit()
}
// const preValue=changes['searchResults'].previousValue;
// const curValue=changes['searchResults'].currentValue;
// if(preValue!=curValue){
// this.ngAfterViewInit()
// }
}
ngAfterViewInit(){
this.map=new Map(
{
container:document.getElementById('map'),
style: 'mapbox://styles/mapbox/streets-v11',
center: { lng: -102.380979, lat: 35.877742 },
zoom: 9,
pitch: 20,
attributionControl: false
});
this.map.addControl(
new NavigationControl({
showZoom: true,
showCompass: true
}),
'top-right'
);
}
ngOnDestroy(){
this.map.remove();
}
}
The container property of the map<div id="map"> is available once the statement in *ngIf returns true / has completed. This is not the case as long as your loadMap() has not finished. Therefore you cannot identify the container.
--> The container needs to exist before you make the function call.
Related
I´m trying to add markers to my map from mapbox.
This is my Angular TypeScript code.
export class MappViewComponent implements OnInit {
map: mapboxgl.Map;
lat = 41.1293;
lng = -8.4464;
style = "mapbox://styles/mapbox/streets-v11";
zoom = 8;
constructor(
private mapService: MapService,
private nodeService: NodeService
) {}
ngOnInit() {
this.buildMap(this.map);
/*var mymap = L.map('mapID').setView([41.260555, -8.436098], 10);
this.buildMap(mymap);*/
this.addMarkersLines(this.map);
new mapboxgl.Marker().setLngLat([this.lng, this.lat]).addTo(this.map);
}
/**https://leafletjs.com/reference-1.7.1.html */
buildMap(map: any) {
map = new mapboxgl.Map({
accessToken:
"accessToken",
container: "mapID",
style: this.style,
zoom: this.zoom,
center: [this.lng, this.lat],
antialias: true,
attributionControl: false,
});
map.addControl(new mapboxgl.NavigationControl());
The problem is that, after running in console it throws this error on this line:
new mapboxgl.Marker().setLngLat([this.lng, this.lat]).addTo(this.map);
ERROR TypeError: t is undefined
addTo mapbox-gl.js:35
ngOnInit mapp-view.component.ts:30
Does anyone have this kind of problem?
Most likely the error occurs since this.map is undefined here:
new mapboxgl.Marker().setLngLat([this.lng, this.lat]).addTo(this.map);
^^^^^^^^
undefined
The way how function buildMap is implemented, it does not affect the object passed, meaning this.map stays undefined in your case. Try to refactor buildMap function, for example:
buildMap() {
this.map = new mapboxgl.Map({
accessToken: MAPBOX_TOKEN,
container: 'mapID',
style: this.style,
zoom: this.zoom,
center: [this.lng, this.lat],
antialias: true,
attributionControl: false,
});
this.map.addControl(new mapboxgl.NavigationControl());
}
Usage
ngOnInit() {
this.buildMap();
new mapboxgl.Marker().setLngLat([this.lng, this.lat]).addTo(this.map);
}
Using esri-loader, when trying to create a SceneView using the following the view is not calculating the zoom correctly and I'm getting the following errors in the console:
[esri.views.3d.support.cameraUtils] #zoomToScale() Cannot compute scale from zoom without a tiling scheme
client-hook-3.js:1 [esri.views.3d.state.ViewStateManager] #zoom= Invalid zoom 3
let map = new WebMap({
portalItem: {
id: MAP_ID_HERE
}
});
let view = new SceneView({
container: "map",
viewingMode: "local",
map: map,
zoom: 3
});
Does anyone happen to know what is causing this? Looking through the documentation for SceneView it seems this should be valid in the constructor.
I think in this particular case, using a web map as the map, you have to wait for the view to load in order to set the zoom level. If not it will not be able to calculate the scale, that is the cause of the error.
This should work,
let view = new SceneView({
container: "map",
map: map,
viewingMode: "local"
});
view.when(function() {
view.zoom = 3;
});
UPDATE: (leave the other code because I think it clarify the problem and the final answer)
Well it seems that is not enough to wait for the view, because the basemap could not load everything. So here you have an alternative that works,
const basemap = Basemap.fromId("dark-gray-vector");
const sceneView = new SceneView({
container: this.$el,
map: new WebMap({
basemap,
}),
center: [US_CENTER.longtitude, US_CENTER.latitude],
viewingMode: "local"
});
basemap.loadAll().then(
() => {
sceneView.goTo({ zoom: 3 });
}
);
In this new solution we actually wait till the basemap loads everything (using loadAll method) an then we set the zoom of the view.
This is the full code in your Map.vue,
<template>
<div />
</template>
<script>
import { loadArcGISModules } from "#deck.gl/arcgis";
const US_CENTER = { longtitude: -98.5795, latitude: 39.8283 };
export default {
name: "Map",
props: {},
mounted() {
loadArcGISModules(
[
"esri/WebMap",
"esri/views/SceneView",
"esri/Basemap",
],
{ css: true }
).then(({ DeckRenderer, modules }) => {
const [WebMap, SceneView, Basemap] = modules;
const basemap = Basemap.fromId("dark-gray-vector");
const sceneView = new SceneView({
container: this.$el,
map: new WebMap({
basemap,
}),
center: [US_CENTER.longtitude, US_CENTER.latitude],
viewingMode: "local"
});
basemap.loadAll().then(
() => {
sceneView.goTo({ zoom: 3 });
}
);
});
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
div {
width: 100%;
height: 100%;
}
</style>
I'm using the google map angular component and it's working pretty good!
But now I want to remove some of the landmarks from the map to reduce its congestion, to be able to show my markers a little more clearly.
I've found these resources below but can't figure out how to apply it to the <google-map> node package I'm using.
Site to create json for hiding landmarks and other features on map
shows how to hide map features from google map dev site
SO link that describes same issue
I see in this google documentation it shows applying styles to 'googlemap' with 'setMapStyle()' but this isn't a method in the angular package
Here below is my component (not all code) where I'm using google maps but it shows how I'm using the all code for the map
import {
MapInfoWindow,
MapMarker,
GoogleMap
} from '#angular/google-maps';
export class YogabandEventsComponent implements OnInit {
colContentRef: ElementRef;
#ViewChild(GoogleMap, {
static: false
}) googleMap: GoogleMap;
#ViewChild(MapInfoWindow, {
static: false
}) infoWindow: MapInfoWindow;
zoom = 12;
center: google.maps.LatLngLiteral;
options: google.maps.MapOptions = {
mapTypeId: 'roadmap',
mapTypeControl: false,
scrollwheel: true,
maxZoom: 18,
minZoom: 10,
streetViewControl: false,
fullscreenControl: false
};
markers: Marker[];
infoContent = '';
constructor(...) { ...
}
openInfo(marker: MapMarker, content) {
this.infoContent = content;
this.infoWindow.open(marker);
}
showMarkers() {
this.markers = [];
for (const ybEvent of this.yogabandEvents) {
const marker = new Marker();
marker.info = ybEvent.name;
marker.title = ybEvent.name;
marker.position = {
lat: ybEvent.latitude,
lng: ybEvent.longitude
};
marker.label = {
color: '#17a2b8',
text: ybEvent.yogaType,
fontWeight: 'bold',
fontSize: '16px'
};
marker.options = {
icon: {
// scaledSize: new google.maps.Size(40, 40),
url: 'assets/images/marker.svg',
labelOrigin: new google.maps.Point(18, 50)
}
};
this.markers.push(marker);
}
}
}
<div class="col flex-fill h-100 px-0 right-col">
<google-map [options]="options" [zoom]="zoom" [center]="center" class="h-100" height="100%" width="100%">
<map-marker #markerElem *ngFor="let marker of markers" [position]="marker.position" [label]="marker.label" [title]="marker.title" [options]="marker.options" (mapClick)="openInfo(markerElem, marker.info)">
</map-marker>
<map-info-window>{{ infoContent }}</map-info-window>
</google-map>
</div>
Try with the styles property of the MapOptions interface.
Like this:
options: google.maps.MapOptions = {
mapTypeId: 'roadmap',
mapTypeControl: false,
scrollwheel: true,
maxZoom: 18,
minZoom: 10,
streetViewControl: false,
fullscreenControl: false,
styles: [...]
};
It could gets a bit annoying styling it detailed. You can generate a set of styles from this Styling Wizard (it also have a Landmarks slide to remove them gradually, then just export the styles array).
I have an overlay placed on a google map:
function CustomerMarker(map) {
this.Map = map;
this.setMap(map);
}
GoogleMap = new google.maps.Map(document.getElementById("map"), {
zoom: 16,
canZoom: false,
center: { lat: lat, lng: lng },
mapTypeControl: false,
streetViewControl: false,
scaleControl: false,
clickableIcons: false
});
CustomMarker.prototype = new google.maps.OverlayView();
CustomMarker.prototype.onAdd = function () {
//Some code
};
CustomMarker.prototype.draw = function () {
//Some code
};
CustomMarker = new CustomMarker(GoogleMap);
Which works fine, and the overlay shows up, however is issue arises when I try to remove that
CustomMarker.setMap(null)
I get an error and the marker remains
Error: this.remove is not a function
pz#https://maps.googleapis.com/maps-api-v3/api/js/30/1/overlay.js:1:251
rk#https://maps.googleapis.com/maps-api-v3/api/js/30/1/overlay.js:2:476
_.pg.prototype.map_changed/<#https://maps.googleapis.com/maps/api
/js?key=AIzaSyBCiIPv6fgrRVn3veTJeP6ihfhrw8AXwbY:125:662
_.G#https://maps.googleapis.com/maps/api/js?key=AIzaSyBCiIPv6fgrRVn3veTJeP6ihfhrw8AXwbY:51:447
_.pg.prototype.map_changed#https://maps.googleapis.com/maps/api/js?key=AIzaSyBCiIPv6fgrRVn3veTJeP6ihfhrw8AXwbY:125:636
Db#https://maps.googleapis.com/maps/api/js?key=AIzaSyBCiIPv6fgrRVn3veTJeP6ihfhrw8AXwbY:37:103
_.k.set#https://maps.googleapis.com/maps/api/js?key=AIzaSyBCiIPv6fgrRVn3veTJeP6ihfhrw8AXwbY:101:728
_.jd/<#https://maps.googleapis.com/maps/api/js?key=AIzaSyBCiIPv6fgrRVn3veTJeP6ihfhrw8AXwbY:55:317
The documentation for OverlayView states:
You must implement three methods: onAdd(), draw(), and onRemove().
I don't see an implementation for onRemove.
Is it possible to re initialize a gmap3 map to its default settings (lat, long, zoom etc)?
I tried destroy on the map and then re run the initialise but it is not working.
See my jsfiddle here - http://jsfiddle.net/vlowe/z9dDE/1/
Wrap the map element in a container div, and then when you want to reset the map, just remove the whole map div and recreate it. This should solve the problem.
According to the gmap3 documentation, you still need to call destroy on the map before removing the dom element.
HTML code
<div>
<div id="map"></div>
</div>
restore
JavaScript
var dlat = 53.9783997; // default map latitude
var dlng = -1.5666347; // default map longitude
var dzoom = 6; // default map zoom
var dmaptype = "roadmap"; // default map type
// create gmap
$('#map').gmap3({
action: 'init',
options: {
center: [dlat, dlng],
zoom: dzoom,
mapTypeId: dmaptype,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
navigationControl: true,
scrollwheel: true,
streetViewControl: true
}
});
function restore() {
$('#map').gmap3({
action: 'destroy'
});
var container = $('#map').parent();
$('#map').remove();
container.append('<div id="map"></div>');
// create new gmap
$('#map').gmap3({
action: 'init',
options: {
center: [dlat, dlng],
zoom: dzoom,
mapTypeId: dmaptype,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
},
navigationControl: true,
scrollwheel: true,
streetViewControl: true
}
});
}
Here's an alternative method:
rather than destroying the map and recreating it entirely, you could save the initial state and the restore it to that state like this: http://jsfiddle.net/UvAL3/1/
(these functions existed as part of the API in V2)