'addLayer' of undefined openlayers angular 4 - angular6

i want add marker by clicking on the map in openlayers angular 6, i want to use addLayer in my function but it doesn't work?
this.map.on('click', function (e) {
console.log(e.coordinate);
var lonlat = e.coordinate;
console.log(lonlat);
var lon = lonlat[0];
var lat = lonlat[1];
this.startMarker = new Feature({
geometry: new Point(fromLonLat([lon, lat])),
});
this.vectorLayer = new VectorLayer({
source: new VectorSource({
features: [this.startMarker]
}),
});
this.map.addLayer(this.startMarker);
});

As well as the this binding and addlayer() parameter, the feature geometry needs to be in view coordinates. e.coordinate is already in view coordinates, so you can use it directly
this.map.on('click', function (e) {
this.startMarker = new Feature({
geometry: new Point(e.coordinate),
});
this.vectorLayer = new VectorLayer({
source: new VectorSource({
features: [this.startMarker]
}),
});
this.map.addLayer(this.vectorLayer);
}.bind(this));

Try the arrow function to keep the context of this.
Your code sample should look like this:
this.map.on('click', (e) => {
console.log('Keep the context of this.map: ', this.map);
console.log(e.coordinate);
var lonlat = e.coordinate;
console.log(lonlat);
var lon = lonlat[0];
var lat = lonlat[1];
this.startMarker = new Feature({
geometry: new Point(fromLonLat([lon, lat])),
});
this.vectorLayer = new VectorLayer({
source: new VectorSource({
features: [this.startMarker]
}),
});
this.map.addLayer(this.startMarker);
});

Related

How to position selected location pin in the center of google map [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
Improve this question
Each location should be at the center of the map when selected from a dropdown of locations. The following code is what I used to implement what I currently have.
For more context, this map was built in webflow ( a low code platform) and I get each location from a collection (cms) list I created. I've called collection: "location" and each location contains a latitude and longitude (that's how the markers are plotted on the map)
How do I center each selected location? What code do I add and where should I add it in my existing code?
<script>
var MAPS = {
zoom: 7,
map: '',
markers: {},
infoWindow: null,
init: function (defaultCoordinates = {}) {
MAPS.create(defaultCoordinates);
MAPS.plotMarkers()
},
create: function (defaultCoordinates = {}) {
var mapDom = document.getElementById('map');
if (!defaultCoordinates['lat']) {
defaultCoordinates.lat = 55.03222;
defaultCoordinates.lng = -2.62529;
}
MAPS.map = new google.maps.Map(mapDom, {
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: true,
mapTypeControl: true,
fullscreenControl: true,
scrollwheel: true,
zoom: MAPS.zoom,
center: defaultCoordinates,
plotMarkers: function () {
var locations = MAPS.locations();
gmarkers = {};
for (var i = 0; i < locations.length; i++) {
gmarkers[locations[i][0]] = MAPS.createMarkers(new google.maps.LatLng(locations[i][2], locations[i][3]), // passing lat and long
locations[i][1]); // passing Info-window information
}
MAPS.markers = gmarkers;
},
initAutoComplete: function () {
var input = document.getElementById('search')
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.addListener('place_changed', () => {
const place = autocomplete.getPlace();
if (place.geometry) {
var lat = place.geometry.location.lat();
var lng = place.geometry.location.lng();
MAPS.init({
lat: lat,
lng: lng
});
var marker = new google.maps.Marker({
position: place.geometry.location,
map: MAPS.map,
});
}
});
},
openMarkerOnClick: function () {
var viewInMap = document.querySelectorAll('[data-marker-open]').addEventListener('click', function () {
console.log('clicked');
})
},
createMarkers: function (latlng, html) {
var marker = new google.maps.Marker({
position: latlng,
map: MAPS.map,
icon: 'https://uploads-ssl.webflow.com/63c7cbc99a05611a1bd1ae5a/63ce964d18ff37a39c305bcd_image%2011.png'
});
// Define info window for each marker
google.maps.event.addListener(marker, 'click', function () {
if (MAPS.infoWindow) {
MAPS.infoWindow.close();
}
console.log(MAPS.infoWindow)
MAPS.infoWindow = new google.maps.InfoWindow();
MAPS.infoWindow.setContent(html);
MAPS.infoWindow.open(MAPS.map, marker);
});
return marker;
},
locations: function () {
// Create a locations array
var locations = []
// Add .location-wrapper class to the location Collection Item
var dynPlaces = document.querySelectorAll('.w-dyn-item.location-item');
// Define variables for the map info window
dynPlaces.forEach(function (elem) {
// Create places array
var place = [];
// Define variables for each place
var dataTitle = elem.querySelector('.data---slug').innerText; // Define slug for targeting the information window
var dataLat = Number(elem.querySelector('.data---latitude').innerText); // Define latitude point for pin
var dataLong = Number(elem.querySelector('.data---longitude').innerText); // Define longitude point for pin
var infoWindowContent = elem.querySelector('.data---info-window').innerHTML; // Define content wrapper for the information window
place.push(dataTitle, infoWindowContent, dataLat, dataLong); // Add variables to each place
locations.push(place); // Add each place to the locations array
});
return locations;
},
build: function (defaultCoordinates = {}) {
MAPS.init(defaultCoordinates);
// MAPS.openMarkerOnClick();
}
}
function initMap() {
MAPS.build();
}
window.onload = (event) => {
MAPS.build();
MAPS.initAutoComplete();
};
</script>

Using Geocorder result in other function in VUe

i try to use the result of Geocode Lag Long, but i can't use out of the function. How can i use the result in other function in Vue?
Why i can't use "this.markerCoordinates" in other functions?
getLocation : function (address){
const element = document.getElementById(this.mapName);
var local;
// geocoder API (pega o endereço)
var geocoder = new google.maps.Geocoder(address);
geocoder.geocode({ 'address': address}, function (results, status){
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
// I WANT USE THIS IN OHTER FUNCTION
this.markerCoordinates = [{"latitude" :latitude , "longitude" : longitude}]
callback( this.markerCoordinates[0])
}
var mapCentre = this.markerCoordinates[0]
var options = {
zoom : 16,
center: new google.maps.LatLng(mapCentre.latitude , mapCentre.longitude)
}
this.options = options;
this.map = new google.maps.Map(element, options);
this.markerCoordinates.forEach((coord) => {
const position = new google.maps.LatLng(coord.latitude, coord.longitude);
const marker = new google.maps.Marker({
position,
map: this.map
});
});
});
},
in other functions is return undefined
Define a data element for your coordinates in your component, see here for an example: data() {return { markerCoordinates: undefined } }
In your getLocation function, you need a closure that points to the enclosing Vue instance , like this let vm = this. See here, e.g.
In the callback, use this variable to access the data element: vm.markerCoordinates = [{"latitude" :latitude , "longitude" : longitude}]
Access the it in the template simply by using markerCoordinates and in other methods of your component with this.markerCoordinates

openlayers3 : center and zoom extent to KML limits

Basic script to display a kml file on a tiled background with openlayer; I just switched from version 2 to 4.65, how can I zoom to the limits of the kml geometry ("vector" here) ?
var wmsSource = new ol.source.TileWMS({
url: "https://sedac.ciesin.columbia.edu/geoserver/wms",
params: {"LAYERS": "other:wwf-terrestrial-biomes", "TILED": true},
serverType: "geoserver"
});
var wmsLayer = new ol.layer.Tile({
opacity: 0.15,
visible: true,
source: wmsSource
});
var vector = new ol.layer.Vector({
source: new ol.source.Vector({
url: "kml_file.kml",
format: new ol.format.KML()
})
});
var map = new ol.Map({
target: "map-canvas",
layers: [wmsLayer, vector],
controls: ol.control.defaults().extend([
new ol.control.ScaleLine({units: "metric"}),
new ol.control.FullScreen()
]),
view: new ol.View({
center: ol.proj.transform([37.41, 8.82], "EPSG:4326", "EPSG:3857"),
zoom: 3
})
});
I'd like to replace the zoom: 3 and have the map centered and extended to the kml limits ?
Note : I used kmllayer.events.register("loadend", kmllayer, function(evt){map.zoomToExtent(kmllayer.getDataExtent())}); with OpenLayers2...
The following should do what you want
var vectorSource = vector.getSource();
vectorSource.once('change', function(e){
if (vectorSource.getState() === 'ready') {
var extent = vectorSource.getExtent();
map.getView().fit(extent);
}
});
Solution mainly adapted from How to get the extent of a GeoJSON vector source? (changed the variable name & removed second argument in map.getView().fit (required in the old time, now optional, not needed most of the time, like here)
OK, I need to declare the kml source as a separate new ol.source.Vectorvariable, here vectorSource, and read .getExtent() from this variable, not from the ol.layer.Vector :
var wmsSource = new ol.source.TileWMS({
url: "https://sedac.ciesin.columbia.edu/geoserver/wms",
params: {"LAYERS": "other:wwf-terrestrial-biomes", "TILED": true},
serverType: "geoserver"
});
var wmsLayer = new ol.layer.Tile({
opacity: 0.15,
visible: true,
source: wmsSource
});
var vectorSource = new ol.source.Vector({
url: "'.$kml_f.'",
format: new ol.format.KML()
});
var vector = new ol.layer.Vector({
source: vectorSource
});
var map = new ol.Map({
target: "map-canvas",
layers: [wmsLayer, vector],
controls: ol.control.defaults().extend([
new ol.control.ScaleLine({units: "metric"}),
new ol.control.FullScreen()
]),
view: new ol.View({
center: ol.proj.transform([37.41, 8.82], "EPSG:4326", "EPSG:3857"),
zoom: 4,
})
});
vector.once("change", function(e){
var extent = vectorSource.getExtent();
map.getView().fit(extent);
});
Thanks for your help !

google maps click event isn't reading objects from data

I'm trying to get latitude and longitude by clicking on map then I use them to get formatted address from google maps API and finally I want to persist lat, lng and formatted address in my object "station" declared in data
data() {
return {
station: {},
mapName: this.name + "-map",
lat: Number,
lng: Number,
Fulladdress: String
};
} ,
mounted() {
const element = document.getElementById(this.mapName);
const options = {
zoom: 14,
center: new google.maps.LatLng(51.501527, -0.1921837)
};
const map = new google.maps.Map(element, options);
google.maps.event.addListener(map, "click", function(event) {
this.lat = event.latLng.lat();
this.lng = event.latLng.lng();
axios
.get(
"https://maps.googleapis.com/maps/api/geocode/json?latlng=" +
this.lat +
"," +
this.lng +
"&key=APIKEY"
)
.then(resp => {
var fulladdress;
console.log(resp.data.results[0].formatted_address);
fulladdress = resp.data.results[0].formatted_address;
this.Fulladdress = fulladdress;
//persist lat, lng and formatted address in my object station
this.station.address = this.Fulladdress;
this.station.lat = this.lat;
this.station.lng = this.lng;
})
.catch(e => {
console.log(e);
});
});
}
The context is changing. Inside the click handler, the this is not referring to the Vue instance, but something else (it depends on how google maps does it, but it could be window or the map instance).
To have the this be the Vue instance, use arrow functions instead.
Change from:
google.maps.event.addListener(map, "click", function(event) {
To:
google.maps.event.addListener(map, "click", (event) => {

Dynamic Load of Heatmap Data based on Map Bounds, Performance Issue

I have implemented a simple page that uses a listener to determine when a google maps bounds have changed because of zoom or pan. I am dynamically loading json data for a weighted heatmap summarized by the area visible in the map. It is working all except for the fact that I am not properly clearing the previous data from the heatmap on each call to the listener. Performance begins to degrade after the 4th or 5th call to fetch new data. I tried setting heatmap to null. What else is needed to maintain performance?
var map, heatmap;
var heatMapData = [];
function initMap() {
var uluru = { lat: 32.673363, lng: -97.399290 };
map = new google.maps.Map(document.getElementById('map'), {
zoom: 14,
center: uluru
});
google.maps.event.addListener(map, "bounds_changed", function () {
heatmap = null;
var bounds = map.getBounds();
//TODO: implement async request
var Httpreq = new XMLHttpRequest(); // a new request
var boxRequest = 'HeatMapData?lmin=' + bounds.f.f + '&lmax=' + bounds.f.b + '&lnmin=' + bounds.b.b + '&lnmax=' + bounds.b.f;
Httpreq.open("GET", boxRequest, false);
Httpreq.setRequestHeader("Content-type", "application/json")
var heatMapJSON = Httpreq.responseText;
heatMapData = [];
var parsedJSON = JSON.parse(heatMapJSON);
for (var i = 0; i < parsedJSON.length; i++) {
heatMapData.push({ location: new google.maps.LatLng(parsedJSON[i].Lat, parsedJSON[i].Lon), weight: parsedJSON[i].weight })
};
console.info('map points: ' + parsedJSON.length.toString());
heatmap = new google.maps.visualization.HeatmapLayer({
data: heatMapData,
map : map
});
});
if (heatmap != null) {
heatmap.setMap(null);
};