JavaScript - leaflet, adding a bunch of markers - javascript

Let's say I have a bunch of markers (over 100) I want to add from this:
module.exports = [
{ value: 'Varrock', lng: 22.5, lat: -15.52249812756166, popular: 1 },
{ value: 'Lumbridge', lng: 25.9661865234375, lat: -43.644025847699496, popular: 1 },
{ value: 'Monastery', lng: -4.0924072265625, lat: -5.714379819235291 },
{ value: 'Edgeville', lng: 2.4884033203125, lat: -6.0094592380595495, popular: 1 },
{ value: 'Varrock Palace', lng: 22.412109375, lat: -6.882800241767556 },
{ value: 'Digsite', lng: 46.043701171875, lat: -17.266727823520508 },
{ value: 'River Salve', lng: 54.931640625, lat: -14.083301314706778 },
{ value: 'Morytania', lng: 64.610595703125, lat: -13.501814172428656 },
{ value: 'Mort Myre Swamp', lng: 59.820556640625, lat: -22.740723091194727 }
];
It uses browserify to get it. So, I do this:
var locations = require('./locations');
What would be the best way to add all of those into LayerGroup()? I mean, because doing var fairy = L.layerGroup([One, Two, Three...]); by hand would get tiresome.
So how would I go about adding all of those markers into a new layer (so I can toggle them on/off)

How about adding an empty L.LayerGroup, looping over your array and adding them to that layer?
var locations = [];
var layer = L.layerGroup().addTo(map);
locations.forEach(function (location) {
L.marker([location.lat, location.lng])
.bindPopup(location.value)
.addTo(layer);
});
Working example on Plunker: http://plnkr.co/edit/Q0DGqs?p=preview

Related

React Google Maps API - containsLocation "b.get is not a function"

I am creating a marker where the map is clicked and I want to know if this marker is inside or outside the polygon. I use the containsLocation function for this, but I keep getting the following error "TypeError: b.get is not a function". Thank you in advance for your answers.
function App() {
const refPoly = useRef(null);
const [position, setPosition] = useState(null);
const center = {
lat: 25.774,
lng: -80.19,
};
const containerStyle = {
position: "absolute",
width: "70%",
height: "70%",
};
const bermudaTriangle = [
{ lat: 25.774, lng: -80.19 },
{ lat: 18.466, lng: -66.118 },
{ lat: 32.321, lng: -64.757 },
];
const google = window.google;
const onHandleClickMap = (event) => {
setPosition({ lat: event.latLng.lat(), lng: event.latLng.lng() });
console.log(
google.maps.geometry.poly.containsLocation(event.latLng, bermudaTriangle)
);
};
return (
<div className="App">
<LoadScript
googleMapsApiKey={GOOGLE_MAPS_API_KEY}
id="script-loader"
libraries={["geometry"]}
>
<GoogleMap
mapContainerStyle={containerStyle}
center={center}
zoom={18}
onClick={onHandleClickMap}
>
<Polygon
ref={refPoly}
paths={bermudaTriangle}
strokeColor="#0000FF"
strokeOpacity={0.8}
strokeWeight={2}
fillColor="#0000FF"
fillOpacity={0.35}
/>
{position && <Marker position={position} />}
</GoogleMap>
</LoadScript>
</div>
);
}
I had the same issue; I solved it like this:
Instead of:
const bermudaTriangle = [
{ lat: 25.774, lng: -80.19 },
{ lat: 18.466, lng: -66.118 },
{ lat: 32.321, lng: -64.757 },
];
...I wrote the bermudaTriangle like this:
const bermudaTriangle = new window.google.maps.Polygon({
paths: polygons[0].paths,
});
console.log(window.google.maps.geometry.poly.containsLocation(
{ lat: event.latLng.lat(), lng: event.latLng.lng() },
bermudaTriangle)
);

Drawing a circle around a point in vue2-google-maps

I am using Vue to build a site that takes in some data and displays a google map with markers and circles around the points with the markers.
So far I can create the map with markers perfectly fine, however I have no idea what the proper way to create a circle is with the Vue2-google-maps package, despite having combed through the Documentation for a long time.
Here is the code so far
<GmapMap
:center="center"
:zoom="10"
class="google-map">
<GmapMarker
:key="index"
v-for="(pin, index) in markers"
:position="pin.position"
:icon="pin.icon"
:clickable="true"
:draggable="true"
#click="center=pin.position">
</GmapMarker>
<GmapCircle
:key="index"
v-for="(pin, index) in markers"
:center="pin.position"
:radius="1000"
:visible="true"
:fillColor="red"
:fillOpacity:="1.0">
</GmapCircle>
</GmapMap>
Note that markers is a list of markers that is created somewhere else in the code.
If you take out the tags, the code works perfectly fine placing all the markers. I just need to know what the proper tag/object set is for creating a circle.
You are on the right track, GmapCircle component in vue2-google-maps library is intended for creating circles on the map. There are might be several reasons why circles are not getting displayed:
center property value is invalid, the supported format is {lat: <lat>, lng: <lng>} or google.maps.LatLng value
maybe you could not spot them due to relatively small size (given the provided 2 kilometer diameter, they could be easily missed)?
Regarding fillColor and fillOpacity properties, they need to be passed via options property, e.g. :options="{fillColor:'red',fillOpacity:1.0}"
Anyway the following example demonstrates how to create circles on map via vue2-google-maps
<GmapMap :center="center" :zoom="zoom" ref="map">
<GmapCircle
v-for="(pin, index) in markers"
:key="index"
:center="pin.position"
:radius="100000"
:visible="true"
:options="{fillColor:'red',fillOpacity:1.0}"
></GmapCircle>
</GmapMap>
export default {
data() {
return {
zoom: 5,
center: { lat: 59.339025, lng: 18.065818 },
markers: [
{ Id: 1, name: "Oslo", position: { lat: 59.923043, lng: 10.752839 } },
{ Id: 2, name: "Stockholm", position: { lat: 59.339025, lng: 18.065818 } },
{ Id: 3, name: "Copenhagen", position: { lat: 55.675507, lng: 12.574227 }},
{ Id: 4, name: "Berlin", position: { lat: 52.521248, lng: 13.399038 } },
{ Id: 5, name: "Paris", position: { lat: 48.856127, lng: 2.346525 } }
]
};
},
methods: {}
};
in my case, i had error that saw:" GmapCircle not define component", so i have used this code:
<gmap-circle
v-for="(infoWindow, index) in arrayMarkers"
:key="'circle_'+index"
radius="100"
:center="infoWindow.position"
/>

Make a user editable polygon on Google maps using ionic 3

i am getting only normal polygon line when my marker is placed on map.
#ionic/cli-utils : 1.19.2
ionic (Ionic CLI) : 3.20.0
global packages:
cordova (Cordova CLI) : 8.0.0
local packages:
#ionic/app-scripts : 3.1.8
Cordova Platforms : android 7.0.0
Ionic Framework : ionic-angular 3.9.2
System:
Android SDK Tools : 26.1.1
Node : v8.10.0
npm : 5.6.0
OS : Windows 10
Environment Variables:
ANDROID_HOME : C:\Users\w2s-pc\AppData\Local\Android\Sdk
Misc:
backend : pro
Code:
import { NavController } from 'ionic-angular';
import{LatLng,GoogleMaps,GoogleMap,GoogleMapsEvent,GoogleMapOptions,
CameraPosition,MarkerOptions,Polyline,Polygon,PolygonOptions,
Spherical,Marker} from '#ionic- native/google-maps';
import { Component } from "#angular/core/";
import { Geolocation } from '#ionic-native/geolocation';
#Component({
selector: 'home',
templateUrl: 'home.html'
})
export class HomePage {
map: GoogleMap;
me: any;
locations = []
constructor() { }
ionViewDidLoad() {
this.loadMap();
}
loadMap() {
let mapOptions: GoogleMapOptions = {
// camera: {
// target: {
// lat: this.me._x,
// lng: this.me._y
// },
// zoom: 18,
// tilt: 30,
// },
MyLocation:true,
MyLocationButton:true,
disableDefaultUI: true,
mapType: "MAP_TYPE_HYBRID",
};
let map= this.map = GoogleMaps.create('map_canvas', mapOptions);
// var div = document.getElementById("map_canvas");
// var map = new GoogleMaps()
// Wait the MAP_READY before using any methods.
this.map.on(GoogleMapsEvent.MAP_READY)
.subscribe(() => {
console.log('Map is ready!');
this.map.setMyLocationEnabled(true)
this.map.setMyLocationButtonEnabled(true)
this.map.on(GoogleMapsEvent.MAP_CLICK).subscribe((location: any) => {
console.log(location);
this.locations.push(new LatLng(location[0].lat, location[0].lng));
console.log(location);
let PolyLineInfo;
this.map.addPolygon({
'points' : this.locations ,
'strokeColor' : '# AA00FF' ,
'fillColor' : '# 00FFAA' ,
'strokeWidth' : 4 ,
'editable' :true,
}).then((info: Polyline) => {
// info.setPoints
PolyLineInfo = info;
}
);
this.map.addMarker({
animation: 'DROP',
draggable: true,
position: {
lat: location[0].lat,
lng: location[0].lng,
},
customInfo: this.locations.length - 1
})
.then(marker => {
marker.on(GoogleMapsEvent.MARKER_DRAG_END)
.subscribe((marker) => {
let index = marker[1].get("customInfo");
this.locations[index] = new LatLng(marker[0].lat, marker[0].lng);
PolyLineInfo.remove();
console.log(this.locations[0]);
console.log(this.locations[1]);
console.log(this.locations[2]);
let dis = Spherical.computeSignedArea(this.locations);
console.log(dis);
let km = Spherical.computeLength(this.locations);
console.log(km);
this.map.addPolygon({
'points' : this.locations ,
'strokeColor' : '# AA00FF' ,
'fillColor' : '#FF0000' ,
'strokeWidth' : 4 ,
'editable' :true,
}).then((info: Polyline) => {
PolyLineInfo = info;
}
);
});
})
});
});
}
}
i need to do like this using ionic version 3 on Google Map
https://github.com/mapsplugin/cordova-plugin-googlemaps-doc/blob/master/v2.0.0/class/Polygon/getPoints/README.md
var GORYOKAKU_POINTS = [
{lat: 41.79883, lng: 140.75675},
{lat: 41.799240000000005, lng: 140.75875000000002},
{lat: 41.797650000000004, lng: 140.75905},
{lat: 41.79637, lng: 140.76018000000002},
{lat: 41.79567, lng: 140.75845},
{lat: 41.794470000000004, lng: 140.75714000000002},
{lat: 41.795010000000005, lng: 140.75611},
{lat: 41.79477000000001, lng: 140.75484},
{lat: 41.79576, lng: 140.75475},
{lat: 41.796150000000004, lng: 140.75364000000002},
{lat: 41.79744, lng: 140.75454000000002},
{lat: 41.79909000000001, lng: 140.75465}//,
//{lat: 41.79883, lng: 140.75673}
];
var mapDiv = document.getElementById("map_canvas");
// Create a map with specified camera bounds
var map = plugin.google.maps.Map.getMap(mapDiv, {
camera: {
target: GORYOKAKU_POINTS
}
});
map.addEventListener(plugin.google.maps.event.MAP_READY, function() {
addEditablePolygon(map, GORYOKAKU_POINTS, function(polygon) {
// To do something...
});
});
function addEditablePolygon(map, points, callback) {
// Add a polygon
map.addPolygon({
'points': points,
'strokeColor' : '#AA00FF',
'fillColor' : '#00FFAA',
'width': 10
}, function(polygon) {
// polygon.getPoints() returns an instance of the BaseArrayClass.
var mvcArray = polygon.getPoints();
// Add draggable markers
mvcArray.map(function(latLng, cb) {
map.addMarker({
position: latLng,
draggable: true
}, cb);
}, function(markers) {
// If a marker is dragged, set the position of it to the points of the Polygon.
markers.forEach(function(marker, idx) {
marker.on(plugin.google.maps.event.MARKER_DRAG, function(position) {
mvcArray.setAt(idx, position);
});
});
callback(polygon);
});
});
}

Using dropDown menu to assign values to variables with knockout

My goal is to use an if statement to give a value from another variable on my code.
HTML
<div id="countryContainer">
<div class="label">
Country:
</div>
<select id="countryDropDown"
data-bind="options: availableCountries,
optionsText: 'countryName',
value: selectedCountry">
</select>
</div>
Javascript
var mxLocations = [
{title: 'Monterrey', location: {lat: 25.6475262, lng: -100.4524278 }},
{title: 'Tulum, Quintana Roo', location: {lat: 20.2114185, lng: -87.4653502 }},
{title: 'Tijuana', location: {lat: 32.5335808, lng: -117.1236801 }},
{title: 'Guadalajara', location: {lat: 20.676856, lng: -103.344773 }}
];
var usLocations = [
{title: 'Laredo', location: {lat: 30.3079827, lng: -97.8934848 }},
{title: 'Venice Beach', location: {lat: 33.9799948, lng: -118.478614 }},
{title: 'Miami', location: {lat: 25.7825453, lng: -80.2994983 }},
{title: 'Wichita', location: {lat: 37.6647979, lng: -97.5837763 }}
];
var home = [
{title: 'Laredo', location: {lat: 30.3079827, lng: -97.8934848 }}
];
var allLocations = (mxLocations.concat(usLocations)).concat(home);
var locations = ""
function getData(dropdown) {
var value = dropdown.options[dropdown.selectedIndex].value;
alert(this.value);
}
// Knockout Constructor
var Country = function(name) {
this.countryName = ko.observable(name);
};
var viewModel = {
availableCountries : ko.observableArray([
new Country("All Locations"),
new Country("Home"),
new Country("Mexico"),
new Country("USA")
]),
selectedCountry : ko.observable() // Nothing selected by default
};
ko.applyBindings(viewModel);
This is what I want to accomplish, if a value from the dropDown menu is selected I want to give the value of a variavle to another variable
function locations() {
if (dropDownValue == "All Locations") {
var locations = allLocations;
} else if (dropDownValue == "Home") {
var locations = home;
} else if (dropDownValue == "Mexico") {
var locations = mxLocations;
} else if (dropDownValue == "USA") {
var locations = usLocations;
I've been looking in all over the place to accomplish this with no result I hope you can address me to the right dirrection
You can subscribe to the selectedCountry observable. The callback function passed as a parameter to the subscribe will be called every time selectedCountry changes.
Here's a working snippet:
var mxLocations = [
{title: 'Monterrey', location: {lat: 25.6475262, lng: -100.4524278 }},
{title: 'Tulum, Quintana Roo', location: {lat: 20.2114185, lng: -87.4653502 }},
{title: 'Tijuana', location: {lat: 32.5335808, lng: -117.1236801 }},
{title: 'Guadalajara', location: {lat: 20.676856, lng: -103.344773 }}
];
var usLocations = [
{title: 'Laredo', location: {lat: 30.3079827, lng: -97.8934848 }},
{title: 'Venice Beach', location: {lat: 33.9799948, lng: -118.478614 }},
{title: 'Miami', location: {lat: 25.7825453, lng: -80.2994983 }},
{title: 'Wichita', location: {lat: 37.6647979, lng: -97.5837763 }}
];
var home = [
{title: 'Laredo', location: {lat: 30.3079827, lng: -97.8934848 }}
];
var allLocations = (mxLocations.concat(usLocations)).concat(home);
var locations = ""
var Country = function(name) {
this.countryName = ko.observable(name);
};
var viewModel = {
availableCountries: ko.observableArray([
new Country("All Locations"),
new Country("Home"),
new Country("Mexico"),
new Country("USA")
]),
selectedCountry: ko.observable()
};
viewModel.selectedCountry.subscribe(function(selectedValue) {
if (selectedValue.countryName() == "All Locations") {
locations = allLocations;
} else if (selectedValue.countryName() == "Home") {
locations = home;
} else if (selectedValue.countryName() == "Mexico") {
locations = mxLocations;
} else if (selectedValue.countryName() == "USA") {
locations = usLocations;
}
console.log(locations);
});
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="label">
Country:
</div>
<select id="countryDropDown" data-bind="options: availableCountries,
optionsText: 'countryName',
value: selectedCountry">
</select>
Click on Run code snippet to test it out.

Ways to handle more than 23 waypoints Google Maps

I followed the below reference posted by mikep to handle more than 23 waypoints with premier license, it does handle more than 23 waypoints however it's not considering the optimal route with 28 waypoints. Please find the snippet of code below. Please let me know, if I missed anything.
Reference: Exceed 23 waypoint per request limit on Google Directions API (Business/Work level)
<!DOCTYPE html>
<html>
<head>
<title>Distance Matrix service</title>
<style>
#right-panel {
font-family: 'Roboto','sans-serif';
line-height: 30px;
padding-left: 10px;
}
#right-panel select, #right-panel input {
font-size: 15px;
}
#right-panel select {
width: 100%;
}
#right-panel i {
font-size: 12px;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
width: 50%;
}
#right-panel {
float: right;
width: 48%;
padding-left: 2%;
}
#output {
font-size: 11px;
}
</style>
</head>
<body>
<div id="right-panel">
<div id="inputs">
<pre>
var origin1 = {lat: 55.930, lng: -3.118};
var origin2 = 'Greenwich, England';
var destinationA = 'Stockholm, Sweden';
var destinationB = {lat: 50.087, lng: 14.421};
</pre>
</div>
<div>
<strong>Results</strong>
</div>
<div id="output"></div>
</div>
<div id="map"></div>
<script>
function initMap() {
var service = new google.maps.DirectionsService;
var map = new google.maps.Map(document.getElementById('map'));
// list of points
// list of points
var stations = [
{lat: 42.304403, lng: -89.04231900000002, name: 'Station 1'},
{lat: 42.236168, lng: -88.54327699999999, name: 'Station 2'},
{lat: 42.234782, lng: -88.53974299999999, name: 'Station 3'},
{lat: 42.151208, lng: -88.47053599999998, name: 'Station 4'},
{lat: 42.159458, lng: -88.44529899999998, name: 'Station 5'},
{lat: 42.157442, lng: -88.45886899999999, name: 'Station 6'},
{lat: 42.187703, lng: -88.36313100000001, name: 'Station 7'},
{lat: 42.188238, lng: -88.34060099999999, name: 'Station 8'},
{lat: 42.185022, lng: -88.309731, name: 'Station 9'},
{lat: 42.17901, lng: -88.32207499999998, name: 'Station 10'},
{lat: 42.165468, lng: -88.322519, name: 'Station 11'},
{lat: 41.91145, lng: -88.30584899999997, name: 'Station 12'},
{lat: 41.903634, lng: -88.3133890000000, name: 'Station 13'},
{lat: 41.67167, lng: -88.548182, name: 'Station 14'},
{lat: 41.564786, lng: -88.600822, name: 'Station 15'},
{lat: 41.561587, lng: -88.60028599999998, name: 'Station 16'},
{lat: 41.560347, lng: -88.597355, name: 'Station 17'},
{lat: 41.582568, lng: -88.90418599999998, name: 'Station 18'},
{lat: 41.5849, lng: -88.90929499999999, name: 'Station 19'},
{lat: 41.584279, lng: -88.91100, name: 'Station 20'},
{lat: 41.794906, lng: -88.93928299999999, name: 'Station 21'},
{lat: 41.796471, lng: -88.94241299999999, name: 'Station 22'},
{lat: 41.849191, lng: -89.0242670000000, name: 'Station 23'},
{lat: 41.846972, lng: -89.020418, name: 'Station 24'},
{lat: 41.875845, lng: -88.45214199999998, name: 'Station 25'},
{lat: 42.030196, lng: -88.271702, name: 'Station 26'},
{lat: 42.304403, lng: -89.04231900000002, name: 'Station 27'},
// ... as many other stations as you need
];
// Zoom and center map automatically by stations (each station will be in visible map area)
var lngs = stations.map(function(station) { return station.lng; });
var lats = stations.map(function(station) { return station.lat; });
map.fitBounds({
west: Math.min.apply(null, lngs),
east: Math.max.apply(null, lngs),
north: Math.min.apply(null, lats),
south: Math.max.apply(null, lats),
});
// Show stations on the map as markers
for (var i = 0; i < stations.length; i++) {
new google.maps.Marker({
position: stations[i],
map: map,
title: stations[i].name
});
}
// Divide route to several parts because max stations limit is 25 (23 waypoints + 1 origin + 1 destination)
for (var i = 0, parts = [], max = 25 - 1; i < stations.length; i = i + max)
parts.push(stations.slice(i, i + max + 1));
// Service callback to process service results
var service_callback = function(response, status) {
if (status != 'OK') {
console.log('Directions request failed due to ' + status);
return;
}
var renderer = new google.maps.DirectionsRenderer;
renderer.setMap(map);
renderer.setOptions({ suppressMarkers: true, preserveViewport: true });
renderer.setDirections(response);
};
// Send requests to service to get route (for stations count <= 25 only one request will be sent)
for (var i = 0; i < parts.length; i++) {
// Waypoints does not include first station (origin) and last station (destination)
var waypoints = [];
for (var j = 1; j < parts[i].length - 1; j++)
waypoints.push({location: parts[i][j], stopover: false});
// Service options
var service_options = {
origin: parts[i][0],
destination: parts[i][parts[i].length - 1],
waypoints: waypoints,
optimizeWaypoints: true,
travelMode: 'DRIVING'
};
// Send request
service.route(service_options, service_callback);
}
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyABPfm9lb39EOvsKMyrdnwdTJSN8IjqVy0&callback=initMap">
</script>
</body>
</html>
Global minima is not possible in that case using Google's API. We have to have an approximation -
Iteratively, cluster 20-25 points together and generate route based on that; Select one master point from the 20-25 points from each cluster - it can be 1st point/one in the middle by comparing averages etc,.
Generate another calcRoute using cluster's master points. Based on this, try to generate a broad route between clusters and route between clusters.

Categories