Angularjs Google maps connect multiple markers - angularjs

I am building an Ionic app and therein I have the following requirement:
I want to use Google maps and I want to be able to mark three markers on the map -> connect those three markers automatically -> and calculate the area it covered.
I have following (map is shown on the screen, I can add multiple markers):
Controller:
angular.extend($scope, {
map: {
center: {
latitude: 51.718921,
longitude: 8.757509
},
zoom: 11,
markers: [],
events: {
click: function (map, eventName, originalEventArgs) {
var e = originalEventArgs[0];
var lat = e.latLng.lat(),lon = e.latLng.lng();
var marker = {
id: Date.now(),
icon: 'http://maps.google.com/mapfiles/ms/icons/blue.png',
coords: {
latitude: lat,
longitude: lon
},
};
$scope.map.markers.push(marker);
console.log($scope.map.markers);
$scope.$apply();
}
}
}
});
HTML:
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" events="map.events">
<ui-gmap-marker ng-repeat="m in map.markers" coords="m.coords" icon="m.icon" idkey="m.id"></ui-gmap-marker>
</ui-gmap-google-map>
How can I proceed further? Code snippets?

To connect markers you could utilize google.maps.Polyline object, in Angular Google Maps library there is a ui-gmap-polyline directive for that purpose.
Example
angular.module('map-example', ['uiGmapgoogle-maps'])
.controller('MapController', function ($scope, $http, uiGmapGoogleMapApi, uiGmapIsReady) {
$scope.map = {
zoom: 2,
bounds: {},
center: { latitude: 0.0, longitude: 180.0 },
markers: [
{ "id": 1, "coords": { "latitude": 37.772323, "longitude": -122.214897 } },
{ "id": 2, "coords": { "latitude": 21.291982, "longitude": -157.821856 } },
{ "id": 3, "coords": { "latitude": -18.142599, "longitude": 178.431 } },
{ "id": 4, "coords": { "latitude": -27.46758, "longitude": 153.027892 } }
]
};
$scope.map.polyline =
{
"path": $scope.map.markers.map(function (m) {
return {
"latitude": m.coords.latitude,
"longitude": m.coords.longitude
};
}),
"stroke": {
"color": '#6060FB',
"weight": 3
},
"geodesic": true,
"visible": true
};
});
.angular-google-map-container {
height: 450px;
width: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.0.1/lodash.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="http://cdn.rawgit.com/nmccready/angular-simple-logger/0.0.1/dist/index.js"></script>
<script src="https://cdn.rawgit.com/angular-ui/angular-google-maps/master/dist/angular-google-maps.min.js"></script>
<div ng-app="map-example" ng-controller="MapController">
<ui-gmap-google-map center="map.center" zoom="map.zoom" draggable="true" events="map.events">
<ui-gmap-marker ng-repeat="m in map.markers" coords="m.coords" icon="m.icon" idkey="m.id"></ui-gmap-marker>
<ui-gmap-polyline path="map.polyline.path" stroke="map.polyline.stroke" visible='map.polyline.visible' geodesic='map.polyline.geodesic' fit="false"></ui-gmap-polyline>
</ui-gmap-google-map>
</div>

Related

Angular google maps giving an error

I am trying to get angular google maps to work, but I am encountering these errors.
angular.js:88 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.6.5/$injector/modulerr?
The above error continues for about half a page.
https://csi.gstatic.com/csi?v=2&s=mapsapi3&v3v=29.10&action=apiboot2&e=10_1_0,10_2_0&rt=main.31 net::ERR_BLOCKED_BY_CLIENT
index.html
<!DOCTYPE HTML>
<html>
<head>
<style>
html,
body {
height: 100%;
}
.angular-google-map-container {
height: 100vh;
}
</style>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/
angular.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js">
</script>
<script src="./node_modules/angular-google-maps/dist/angular-google-
maps.js"></script>
<script src="./map.controller.js"></script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBL3uzNfWSpztGvmqhBLf-
gYdfdxrCSOQo">
</script>
</head>
<body>
<div ng-app="myApp" ng-controller="gMap">
<ui-gmap-google-map center='map.center' zoom='map.zoom' aria-
label="Google map">
<ui-gmap-marker ng-repeat="marker in markers" coords="marker.coords"
options="marker.options" events="marker.events" idkey="marker.id">
<ui-gmap-window>
<div>{{marker.window.title}}</div>
</ui-gmap-window>
</ui-gmap-marker>
</ui-gmap-google-map>
</div>
</body>
</html>
app and controller
var myApp = angular.module('myApp', ['uiGmapgoogle-maps']);
myApp.factory("Markers", function(){
var Markers = [
{
"id": "0",
"coords": {
"latitude": "45.5200",
"longitude": "-122.6819"
},
"window": {
"title": "Portland, OR"
}
},
{
"id": "1",
"coords": {
"latitude": "40.7903",
"longitude": "-73.9597"
},
"window" : {
"title": "Manhattan New York, NY"
}
}
];
return Markers;
});
myApp.controller("gMap",function($scope,Markers){
$scope.map = {
center: { latitude: 39.8282, longitude: -98.5795 },
zoom: 4
};
$scope.markers = Markers;
});
Can someone please help me solve this?
You need to correct your Markers factory implementation, factory must return an object.
So change it like :
myApp.factory("Markers", function(){
var Markers = [
{
"id": "0",
"coords": {
"latitude": "45.5200",
"longitude": "-122.6819"
},
"window": {
"title": "Portland, OR"
}
},
{
"id": "1",
"coords": {
"latitude": "40.7903",
"longitude": "-73.9597"
},
"window" : {
"title": "Manhattan New York, NY"
}
}
];
return {
markers: Markers
};
});
Then in your gMap controller, consume factory array like:
$scope.markers = Markers.markers;
Update:
You also need to import angular-simple-logger.js library since it is dependecy of googlemap api. See this fiidle

How to show Google maps and leaflet draw polygons in a same layer?

I am able to display marker & geojson polygons using leaflet and google maps.but map and polygons are coming in different layers this is not looking good when you zoom in,zoom out or while dragging .How can I display them in a same layer? here is the plunker!
<!DOCTYPE html>
<html>
<style>
.leaflet-google-layer {
z-index: 0 !important;
}
.leaflet-map-pane {
z-index: 100;
}
</style>
<head>
<title>Leaflet Draw</title>
<link rel="stylesheet" href="https://leaflet.github.io/Leaflet.draw/lib/leaflet/leaflet.css" />
<link rel="stylesheet" href="https://leaflet.github.io/Leaflet.draw/leaflet.draw.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="lib/leaflet/leaflet.ie.css" />
<link rel="stylesheet" href="leaflet.draw.ie.css" />
<![endif]-->
<script src="https://leaflet.github.io/Leaflet.draw/lib/leaflet/leaflet.js"></script>
<script src="https://leaflet.github.io/Leaflet.draw/leaflet.draw.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://maps.google.com/maps/api/js?v=3.25"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div id="map" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
var map = new L.Map('map', {
center: new L.LatLng(-37.7772, 175.2756),
zoom: 9
});
var googleLayer = new L.Google('ROADMAP');
map.addLayer(googleLayer);
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
var drawControl = new L.Control.Draw({
draw: {
position: 'topleft',
polygon: {
title: 'Draw a sexy polygon!',
allowIntersection: false,
drawError: {
color: '#b00b00',
timeout: 1000
},
shapeOptions: {
color: '#bada55'
},
showArea: true
},
polyline: {
metric: false
},
circle: {
shapeOptions: {
color: '#662d91'
}
}
},
edit: {
featureGroup: drawnItems
}
});
map.addControl(drawControl);
map.on('draw:created', function(e) {
var type = e.layerType,
layer = e.layer;
if (type === 'marker') {
layer.bindPopup('A popup!');
}
drawnItems.addLayer(layer);
var geoPoints = layer.toGeoJSON();
console.log(geoPoints);
});
map.on('draw:edited', function(e) {
var layers = e.layers;
layers.eachLayer(function(layer) {
var geoPoints = layer.toGeoJSON();
console.log(geoPoints);
});
});
map.on('draw:deleted', function(e) {
var layers = e.layers;
layers.eachLayer(function(layer) {
var geoPoints = layer.toGeoJSON();
console.log(geoPoints);
});
});
L.geoJson($scope.geojsonFeatures, {
onEachFeature: onEachFeature
});
$scope.geojsonFeatures = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
175.2756, -37.7772
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
175.27364730834958, -37.77322501372662
],
[
175.27849674224854, -37.776617142149554
],
[
175.28351783752439, -37.784486280685925
],
[
175.28879642486572, -37.781365860467126
],
[
175.2824878692627, -37.7707486617024
],
[
175.27364730834958, -37.77322501372662
]
]
]
}
}]
};
console.log($scope.geojsonFeatures);
L.geoJson($scope.geojsonFeatures, {
onEachFeature: onEachFeature
});
function onEachFeature(feature, layer) {
drawnItems.addLayer(layer);
}
});
</script>
</body>
</html>
Cannot be done. The current implementations of Leaflet plugins for displaying Google maps imply creating a GMaps instance, and trying to keep its view (center and zoom) in sync with Leaflet's view.
This is hackish but currently the only way to do this - and has the obvious disadvantage of not syncing up the pan and zoom transitions (which use different inertia, speed curves and interpolation in both libraries).
Edit: I just created the GoogleMutant Leaflet plugin a couple days ago, which should help with this whole affair.

Angular Google Maps can not click on marker the second time

I created a custom marker, I click on it, the info window opens. Then I close the info window. I try to click on the marker again but the info window doesn't open. It works on the other two markers fine.
Below is the plunker sample.
Thanks for the help.
http://plnkr.co/edit/hzfAkQ5UJBLz3BZEy8M9?p=preview
'use strict';
angular.module('app', ['uiGmapgoogle-maps'])
.controller('locatorController', function($scope, $timeout, uiGmapGoogleMapApi) {
var pinSymbol = function(color) {
// console.log("color: "+color);
return {
path: 'M 0,0 C -2,-20 -10,-22 -10,-30 A 10,10 0 1,1 10,-30 C 10,-22 2,-20 0,0 z',
fillColor: color,
fillOpacity: 1,
strokeColor: '#FFFFFF',
strokeWeight: 1.3,
scale: 1.3
};
}
$scope.map = {
center: {
latitude: 39,
longitude: -98
},
control: {},
zoom: 8,
window: {
model: {},
show: false,
options:{
pixelOffset: {width:-1,height:-20}
}
},
markers: [{
"id": "1",
"latitude": "39.05",
"longitude": "-98.55",
options: {
labelContent : '$23',
labelAnchor: "14 75",
labelClass: 'labelClass',
icon: pinSymbol('green'),
labelInBackground: false
}
}, {
"id": "2",
"latitude": "39.15",
"longitude": "-98.45"
}, {
"id": "3",
"latitude": "39.25",
"longitude": "-97.95"
}, ],
markersEvents: {
click: function(marker, eventName, model, args) {
$scope.$apply(function () {
$scope.map.window.model = model;
$scope.map.window.show = true;
});
}
}
};
})
.controller('templateController',function(){});
.location-finder .angular-google-map,
.location-finder .angular-google-map-container {
height: 30em;
}
.selected {
background: #ddd;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div ng-app="app" ng-controller="locatorController" class="location-finder">
<ui-gmap-google-map center="map.center" zoom="map.zoom" control="map.control">
<!-- Map Pins -->
<ui-gmap-markers models="map.markers" idKey="'id'" coords="'self'" options="'options'" events="map.markersEvents">
</ui-gmap-markers>
<!-- InfoWindows -->
<!-- this works, but infowindow is not attached to marker -->
<ui-gmap-window
show="map.window.show"
coords="map.window.model"
templateUrl="'test'"
templateParameter="map.window.model"
options="map.window.options"
ng-cloak>
</ui-gmap-window>
<!-- try this instead of the above and the template does not load -->
<!-- <ui-gmap-window show="map.window.show" coords="map.window.model" templateUrl="'infowindow.tpl'" ng-cloak></ui-gmap-window>-->
</ui-gmap-google-map>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js" charset="utf-8"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.5.0/lodash.js" charset="utf-8"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-google-maps/2.1.0-X.5/angular-google-maps.js" charset="utf-8"></script>
<script src="script.js"></script>
</body>
</html>
http://plnkr.co/edit/hzfAkQ5UJBLz3BZEy8M9?p=preview
I used the following post as guidance.
https://github.com/angular-ui/angular-google-maps/issues/548
I added a hide window value
In the map array, i added the following function:
infoEvents: function (){$scope.map.window.show = false;}
....
}
},
infoEvents: function (){$scope.map.window.show = false;},
doClusterRandomMarkers: true,
clusterOptions: standardClusterType
.....
In the HTML I modified as follows:
closeClick="map.infoEvents"
<ui-gmap-window
show="map.window.show"
coords="map.window.model"
templateUrl="'infowindow.tpl'"
templateParameter="map.window.model"
options="map.window.options"
closeClick="map.infoEvents"
ng-cloak>
</ui-gmap-window>
markers: [{
"id": "1",
"latitude": "39.05",
"longitude": "-98.55",
options: {
labelContent : '$23',
labelAnchor: "11 75",
labelClass: 'labelClass',
icon: pinSymbol('green'),
labelInBackground: true
}
Also, make sure you put the marker options property -> labelInBackground: true
Otherwise, I think the label covers the marker and the events don't register. At least, that is how I interpret it.
That was it.

Updating angularjs controller with websocket data

I'm trying to update my angularjs controller after receiving new information from a websocket server. I am using angular-websockets to create the connection with the websocket server.
Here is my code:
angular.module('VotingApp', ['ngWebSocket'])
.factory('MyVotingResults', function ($websocket) {
// Open a WebSocket connection
var ws = $websocket('ws://localhost:80/test');
//defaults
var collection = {
Question: "This is my question?",
Results: [
{ Percentage: 0, Picture: "http://www.kvmechelen.be/wp-content/uploads/2015/02/De-Witte.jpg", Player: "Seth De Witte", Number: "4", Position: "Defender", Winner: true },
{ Percentage: 0, Picture: "http://www.kvmechelen.be/wp-content/uploads/2016/02/15-16grpsf-037-19715104962_19124904603_o.jpg", Player: "Tim Matthys", Number: "7", Position: "Midfielder", Winner: false },
{ Percentage: 0, Picture: "http://www.kvmechelen.be/wp-content/uploads/2016/02/NICOLAS-VERDIER.jpg", Player: "Nicolas Verdier", Number: "99", Position: "Forward", Winner: false }
]
};
ws.onOpen(function () {
console.log("connectie is open");
ws.send("Hello world!");
});
ws.onClose(function () {
console.log("connectie is closed");
});
ws.onError(function () {
console.log("error!");
});
ws.onMessage(function (response) {
console.log("received an update: ", response);
collection = JSON.parse(response.data);
});
return {
collection: collection,
get: function () {
ws.send(JSON.stringify({ action: 'get' }));
}
};
})
.controller('VotingController', function ($scope, MyVotingResults) {
$scope.Data = MyVotingResults.collection;
})
I am initializing my collection variable with some data to begin. That works and it is shown on the page like it is supposed to.
Here is my html:
<div class="content" ng-controller="VotingController">
<div class="vraag">
<p>{{Data.Question}}</p>
</div>
<div class="antwoorden">
<div class="antw" ng-repeat="result in Data.Results">
<div class="result">
<div class="resultWinner">
<img src="img/winner.png" />
</div>
<div class="resultImage">
<img src="{{result.Picture}}" />
</div>
<div class="resultBalk">
<p><span class="timer">{{result.Percentage}}</span>%</p>
</div>
</div>
<div class="antwText">
<p><span>{{result.Number}}.</span> {{result.Player}}</p>
<p>{{result.Position}}</p>
</div>
</div>
</div>
</div>
My websocketserver is a simple testserver that sends back this json:
{
"Question": "Who deserves the Man of the Match award?",
"Results": [{
"Percentage": 25.0,
"Picture": "http://www.kvmechelen.be/wp-content/uploads/2015/02/De-Witte.jpg",
"Player": "Seth De Witte",
"Number": "4",
"Position": "Defender",
"Winner": false
}, {
"Percentage": 40.0,
"Picture": "http://www.kvmechelen.be/wp-content/uploads/2016/02/15-16grpsf-037-19715104962_19124904603_o.jpg",
"Player": "Tim Matthys",
"Number": "7",
"Position": "Midfielder",
"Winner": true
}, {
"Percentage": 35.0,
"Picture": "http://www.kvmechelen.be/wp-content/uploads/2016/02/NICOLAS-VERDIER.jpg",
"Player": "Nicolas Verdier",
"Number": "99",
"Position": "Forward",
"Winner": false
}]
}
Why won't page update? I based my code on this example:
https://angularclass.github.io/angular-websocket/
Any help is appreciated.
EDIT:
I changed my controller to this but it still doesn't work unfortunately.
.controller('VotingController', function ($scope, MyVotingResults) {
$scope.Data = MyVotingResults.collection;
$scope.$watch(function () {
return MyVotingResults.collection;
}, function (newValue) {
$scope.Data = newValue;
});
})
You can "watch" that service variable in your controller and update the scope accordingly:
$scope.$watch(function () {
return MyVotingResults.collection;
}, function (newValue) {
$scope.Data = newValue;
});

Angular-Leaflet-Directive + JSON markers

Try create Leaflet Map with clustering markers in my app. Using for this Angular Leaflet Directive plugin.
It's work with example controller and JSON data, but I have other JSON with other data format and have problem with get lattitude and longitude parameters for creating markers array on my map.
My Controller
app.controller("BasicFirstController", [ "$scope", "$http", function($scope, $http) {
var addressPointsToMarkers = function(points) {
return points.map(function(ap) {
return {
layer: 'realworld',
lat: ap[0],
lng: ap[1],
message: ap[2]
};
});
};
angular.extend($scope, {
center: {
lat: 53.13207624721133,
lng: 26.01689853383789,
zoom: 15
},
events: {
map: {
enable: ['moveend', 'popupopen'],
logic: 'emit'
},
marker: {
enable: [],
logic: 'emit'
}
},
layers: {
baselayers: {
osm: {
name: 'OSM',
url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
type: 'xyz'
},
overlays: {
realworld: {
name: "Real world data",
type: "markercluster",
visible: true
}
}
}
});
$http.get("sample.json").success(function(data) {
$scope.markers = addressPointsToMarkers(data);
});
}]);
Work with this JSON format
[
[-37.8839, 175.3745188667, "571"],
[-37.8869090667, 175.3657417333, "486"],
[-37.8894207167, 175.4015351167, "807"],
[-37.8927369333, 175.4087452333, "899"],
[-37.90585105, 175.4453463833, "1273"]
]
Need work with this JSON format
{
"posts": [
{
"ID": "1",
"title": "Title",
"tag": "tag1",
"lat": "53.11691211703813",
"lng": "26.03631556034088",
"thumb": "getImage-24-100x100.jpg",
"fullimg": "getImage-24.jpg",
"imgs": [
{
"imgurl": "getImage-24-300x200.jpg"
}
],
"place": "Place",
"type": "Photo",
"period": "War",
"year": "1985",
"url": "site.com",
"author": "author"
},
{
"ID": "2",
"title": "Title2",
"tag": "tag2",
"lat": "53.11691211703813",
"lng": "26.03631556034088",
"thumb": "getImage-24-100x100.jpg",
"fullimg": "getImage-24.jpg",
"imgs": [
{
"imgurl": "getImage-24-300x200.jpg"
}
],
"place": "Place",
"type": "Photo",
"period": "War",
"year": "1935",
"url": "site.com",
"author": "author"
}
]
}
How get data with lat and lng from JSON for markers array?
Here is what worked for me with a JSON file sent from server, to publish ALL markers at once:
Then with $HTTP I can "get" the data, but you will have to loop through it and push details to a new $scope array:
$scope.markers = []
$http.get('JSONfilePath').then(function (responseData) {
for (var i = 0; i < responseData.data.length; i++){
$scope.markers.push({
lat: responseData.data[i].latitude,
lng: responseData.data[i].longitude
})
}
})
In the HTML file, it's pretty straight forward:
<leaflet lf-center="center" defaults="defaults" markers="markers" width="90%" height="800px"></leaflet>

Resources