Add to Angular Model from Outside of Controller - javascript

I want to call the addRectangleMethod method from the javascript in my code so that I can get server side information into the Angular datamodel. I keep getting the error that the method I am trying to call is undefined. The angular is in typescript.
Html
<!DOCTYPE html>
<html >
<head>
<style>
#map-canvas {
width: 800px;
height: 600px;
text-align: center;
}
</style>
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/PosCtrl.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaL- xHTY5NYNS6StKvA0TGsZYx3D44"></script>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
//angular.element($('#Test')).scope().PositionCtrl.addRectangle();
console.log($('#Test'));
var appElement = document.querySelector('[ng-app=myApp]');
var $scope = angular.element(appElement).scope();
$scope.$apply(function () {
$scope.addRectangleMethod(2,2,2,2,"Hello");
});
</script>
</head>
<body id="Test" ng-app="myApp" ng-controller="PositionCtrl as Pos" style="display: inline-block; margin: 0px 0px 0px 550px; text-align: center;">
<div style="height: 100%; width: 100%;">
<div id="map-canvas"></div>
</div>
<div>
<form>
<ul>
<li ng-repeat="x in Pos.rectangles"><input ng-model="x.Name" ng- change="x.tangleChange()" /> <b>South West Corner</b> {{x.Shape.getBounds().O.O}} , {{x.Shape.getBounds().j.j}} <b>North East Corner</b>{{x.Shape.getBounds().O.j}} , {{x.Shape.getBounds().j.O}}<button ng-click="Pos.deleteRec(x)">Delete</button> </li>
</ul>
<button ng-click="Pos.save()">Save Settings</button>
<button ng-click="Pos.addRectangle()">Add Area</button>
</form>
</div>
</body>
#Scripts.Render("~/bundles/bootstrap")
</html>
Angular
/// <reference path="../../OciCP2.0/Scripts/typings/googlemaps/google.maps.d.ts" />
/// <reference path="../../OcCP2.0/Scripts/typings/angularjs/angular.d.ts" />
class Rectangle {
//Rectangle class properties
Shape: google.maps.Rectangle;
InfoWindow: google.maps.InfoWindow;
Name: string;
constructor(map: google.maps.Map, pt1: google.maps.LatLng, pt2: google.maps.LatLng, info: string, $scope: ng.IScope) {
//Set rectangle Options
var options: google.maps.RectangleOptions = {
editable: true,
draggable: true
}
//Create Rectangle
this.Shape = new google.maps.Rectangle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
bounds: new google.maps.LatLngBounds(pt1, pt2),
});
//Attach Options to rectangle
this.Shape.setOptions(options);
this.Name = info;
//Create info window
this.InfoWindow = new google.maps.InfoWindow({
content: info,
position: pt1
});
this.InfoWindow.setPosition(this.Shape.getBounds().getNorthEast());
this.InfoWindow.open(map);
google.maps.event.addListener(this.Shape, 'bounds_changed',() => {
this.InfoWindow.setPosition(this.Shape.getBounds().getNorthEast());
$scope.$apply();
this.InfoWindow.open(map)
});
}
tangleChange() {
//Keep info content up to date
this.InfoWindow.setContent(this.Name);
}
}
class PositionCtrl {
//Proporties of the controller
MyMap: google.maps.Map;
marker: google.maps.Marker;
event: google.maps.event;
rectangles: Rectangle[];
lat: number; long: number; rad: number;
//Save the changes
save() {
alert("Settings Saved");
}
constructor(private $scope: ng.IScope) {
this.lat = 20;
this.long = 20;
this.rad = 10000;
this.rectangles = new Array<Rectangle>();
//Create map and bind to element
var mapCanvas = document.getElementById('map-canvas');
var mapOptions = {
center: new google.maps.LatLng(Number(this.lat), Number(this.long)),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDoubleClickZoom: true
}
this.MyMap = new google.maps.Map(mapCanvas, mapOptions)
}
//Add rectangle to page
addRectangle() {
//Add rectangle to array
this.rectangles.push(
new Rectangle(this.MyMap,
new google.maps.LatLng(this.MyMap.getCenter().lat() - .5, this.MyMap.getCenter().lng() - .5),
new google.maps.LatLng(this.MyMap.getCenter().lat() + .5, this.MyMap.getCenter().lng() + .5), "Enter Name", this.$scope)
);
console.log(this.rectangles);
}
addRectangleMethod(top, bottom, left, right, name) {
console.log("Sucess");
this.rectangles.push(
new Rectangle(this.MyMap,
new google.maps.LatLng(left, bottom),
new google.maps.LatLng(right, top), name, this.$scope)
);
}
//Remove Rectangle from map
deleteRec(x: Rectangle) {
for (var i = 0; i < Rectangle.length; i++) {
if (this.rectangles[i].InfoWindow.getContent() == x.InfoWindow.getContent()) {
x.Shape.setMap(null);
x.InfoWindow.close();
this.rectangles.splice(i, 1);
}
}
this.$scope.$apply();
}
}
var myApp = angular.module('myApp', []);
myApp.controller("PositionCtrl", ["$scope", PositionCtrl]);

Bind the addRectangleMethod from your class to your $scope
constructor(private $scope: ng.IScope) {
this.$scope.addRectangleMethod = () => this.addRectangleMethod();

Related

Show OverlayView marker in street view

I wanted to create custom "HTMLMarker" for google maps, but I just found out, it is not displaying in the street view. I have searched docs, but nothing is written there. (Googled: "show OverlayView marker in street view")
interface HTMLMarkerOptions {
position: google.maps.LatLng | google.maps.LatLngLiteral;
content: HTMLElement;
}
class HTMLMarker extends google.maps.OverlayView {
private _element: HTMLElement;
private _isAppended = false;
private _position: google.maps.LatLng;
constructor(options: HTMLMarkerOptions) {
super();
this._position = this._createLatLng(options.position)
this._element = document.createElement('div');
this._element.style.position = 'absolute';
this._element.appendChild(options.content);
}
_appendDivToOverlay() {
const panes = this.getPanes();
panes.overlayMouseTarget.appendChild(this._element);
this._isAppended = true;
}
_positionDiv() {
const map = this.getMap();
if (map instanceof google.maps.StreetViewPanorama) {
// TODO: Render in StreetView
return;
} else {
const projection = this.getProjection();
const point = projection.fromLatLngToDivPixel(this._position);
if (point) {
this._element.style.left = `${point.x - this._offset.left}px`;
this._element.style.top = `${point.y - this._offset.top}px`;
}
}
}
setMap(map: google.maps.Map | google.maps.StreetViewPanorama | null) {
super.setMap(map);
}
draw() {
if (!this._isAppended) {
this._appendDivToOverlay();
}
this._positionDiv();
}
remove(): void {
this._element.parentNode?.removeChild(this._element);
this._isAppended = false;
}
setPosition(position: google.maps.LatLng | google.maps.LatLngLiteral): void {
if (!this._LatLngEquals(this._position, position)) {
this._position = this._createLatLng(position);
}
}
getPosition(): google.maps.LatLng {
return this._position;
}
getDraggable(): boolean {
return false;
}
private _createLatLng(
position: google.maps.LatLng | google.maps.LatLngLiteral,
): google.maps.LatLng {
if (position instanceof google.maps.LatLng) {
return position;
} else {
return new google.maps.LatLng(position);
}
}
private _LatLngEquals(
positionA: google.maps.LatLng | undefined,
positionB: google.maps.LatLng | google.maps.LatLngLiteral,
): boolean {
if (!positionA) {
return false;
}
if (positionB instanceof google.maps.LatLng) {
return positionA.equals(positionB);
} else {
return positionA.lat() == positionB.lat && positionA.lng() == positionB.lng;
}
}
}
example fiddle (compiled TS to ESNext)
Although the documentation says:
Additionally, when creating a map with a default StreetViewPanorama, any markers created on a map are shared automatically with the map's associated Street View panorama, provided that panorama is visible.
That doesn't seem to be true for the HTMLMarker. Setting the map property of the HTMLMarker to the default Street View panorama of the map:
marker.setMap(map.getStreetView());
makes it visible.
proof of concept fiddle
Related question: Drawing polylines on Google Maps Streetview
code snippet:
const map = new google.maps.Map(
document.querySelector('#map-canvas'), {
zoom: 18,
center: new google.maps.LatLng(37.422, -122.084),
mapTypeId: google.maps.MapTypeId.ROADMAP,
},
);
google.maps.event.addListener(map, 'click', function(e) {
console.log(e.latLng.toUrlValue(6));
})
class HTMLMarker extends google.maps.OverlayView {
constructor(options) {
super();
this._isAppended = false;
this._position = this._createLatLng(options.position);
this._element = document.createElement('div');
this._element.style.position = 'absolute';
this._element.appendChild(options.content);
}
_appendDivToOverlay() {
const panes = this.getPanes();
panes.overlayMouseTarget.appendChild(this._element);
this._isAppended = true;
}
_positionDiv() {
const map = this.getMap();
const projection = this.getProjection();
const point = projection.fromLatLngToDivPixel(this._position);
if (point) {
this._element.style.left = point.x + 'px';
this._element.style.top = point.y + 'px';
}
}
setMap(map) {
super.setMap(map);
}
draw() {
if (!this._isAppended) {
this._appendDivToOverlay();
}
this._positionDiv();
}
remove() {
if (this._element.parentNode) {
this._element.parentNode.removeChild(this._element);
}
this._isAppended = false;
}
setPosition(position) {
if (!this._LatLngEquals(this._position, position)) {
this._position = this._createLatLng(position);
}
}
getPosition() {
return this._position;
}
getDraggable() {
return false;
}
_createLatLng(position) {
if (position instanceof google.maps.LatLng) {
return position;
} else {
return new google.maps.LatLng(position);
}
}
_LatLngEquals(positionA, positionB) {
if (!positionA) {
return false;
}
if (positionB instanceof google.maps.LatLng) {
return positionA.equals(positionB);
} else {
return positionA.lat() == positionB.lat && positionA.lng() == positionB.lng;
}
}
}
const marker = new HTMLMarker({
position: new google.maps.LatLng(37.42197, -122.083627),
content: document.querySelector('#marker'),
});
marker.setMap(map);
const marker1 = new google.maps.Marker({
position: new google.maps.LatLng(37.42197, -122.083627),
});
marker1.setMap(map);
// We get the map's default panorama and set up some defaults.
// Note that we don't yet set it visible.
panorama = map.getStreetView();
panorama.setPosition({
lat: 37.421885,
lng: -122.083662
});
panorama.setPov( /** #type {google.maps.StreetViewPov} */ ({
heading: 0,
pitch: 0
}));
panorama.setVisible(true);
panorama.setZoom(1);
marker.setMap(map.getStreetView());
* {
box-sizing: border-box;
}
body {
margin: 0;
}
#map-canvas {
height: 100vh;
width: 100vw;
background-color: #CCC;
}
#marker {
display: flex;
height: 50px;
width: 50px;
background: white;
border: 3px solid black;
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map-canvas"></div>
<div id="marker">
ID: 1
</div>
I also had a look at this yesterday and as mentioned by geocodezip, the documentation is misleading (or wrong). It mentions that
if you explicitly set the map's streetView property to a StreetViewPanorama of your own construction, you will override the default panorama and disable automatic overlay sharing
which to me would mean that if you are not using a panorama of your own construction (and therefore the default panorama), overlay sharing should work, unless if by "overlay" they meant Marker.
Here is a proof that a standard Marker is shared between the map and the default panorama without the need to do anything and the custom overlay isn't:
var map;
var panorama;
var htmlMarker;
function initialize() {
function HTMLMarker(lat, lng) {
this.lat = lat;
this.lng = lng;
this.pos = new google.maps.LatLng(lat, lng);
this.divReference = null;
}
HTMLMarker.prototype = new google.maps.OverlayView();
HTMLMarker.prototype.onRemove = function() {
this.divReference.parentNode.removeChild(this.divReference);
this.divReference = null;
}
HTMLMarker.prototype.onAdd = function() {
div = document.createElement('DIV');
div.className = "html-marker";
div.style.width = '60px';
div.style.height = '50px';
div.innerHTML = 'ABC';
var panes = this.getPanes();
panes.overlayMouseTarget.appendChild(div);
this.divReference = div;
}
HTMLMarker.prototype.draw = function() {
var overlayProjection = this.getProjection();
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
var panes = this.getPanes();
panes.overlayMouseTarget.style.left = position.x - 30 + 'px';
panes.overlayMouseTarget.style.top = position.y - 25 + 'px';
}
// Set up the map
var mapOptions = {
center: new google.maps.LatLng(40.729884, -73.990988),
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: false
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
panorama = map.getStreetView();
panorama.setPosition(new google.maps.LatLng(40.729884, -73.990988));
panorama.setPov({
heading: 330,
zoom: 1,
pitch: 0
});
htmlMarker = new HTMLMarker(40.729952, -73.991056);
htmlMarker.setMap(map);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(40.729952, -73.991198),
map: map,
draggable: true,
title: 'My marker'
});
}
function toggleStreetView() {
var toggle = panorama.getVisible();
if (toggle == false) {
panorama.setVisible(true);
} else {
panorama.setVisible(false);
}
}
var button = document.getElementsByTagName('input')[0];
button.onclick = function() {
toggleStreetView()
};
#map-canvas {
height: 150px;
}
input {
margin: 10px;
background-color: #4CAF50;
border: none;
color: white;
padding: 4px 8px;
}
.html-marker {
background-color: red;
color: white;
line-height: 50px;
text-align: center;
font-size: 18px;
font-weight: bold;
}
<input type="button" value="Toggle Street View">
<div id="map-canvas"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize" async defer></script>
And here, when changing from map to default panorama, I simply do
htmlMarker.setMap(null);
htmlMarker.setMap(panorama);
and it works.
var map;
var panorama;
var htmlMarker;
function initialize() {
function HTMLMarker(lat, lng) {
this.lat = lat;
this.lng = lng;
this.pos = new google.maps.LatLng(lat, lng);
this.divReference = null;
}
HTMLMarker.prototype = new google.maps.OverlayView();
HTMLMarker.prototype.onRemove = function() {
this.divReference.parentNode.removeChild(this.divReference);
this.divReference = null;
}
HTMLMarker.prototype.onAdd = function() {
div = document.createElement('DIV');
div.className = "html-marker";
div.style.width = '60px';
div.style.height = '50px';
div.innerHTML = 'ABC';
var panes = this.getPanes();
panes.overlayMouseTarget.appendChild(div);
this.divReference = div;
}
HTMLMarker.prototype.draw = function() {
var overlayProjection = this.getProjection();
var position = overlayProjection.fromLatLngToDivPixel(this.pos);
var panes = this.getPanes();
panes.overlayMouseTarget.style.left = position.x - 30 + 'px';
panes.overlayMouseTarget.style.top = position.y - 25 + 'px';
}
// Set up the map
var mapOptions = {
center: new google.maps.LatLng(40.729884, -73.990988),
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: false
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
panorama = map.getStreetView();
panorama.setPosition(new google.maps.LatLng(40.729884, -73.990988));
panorama.setPov({
heading: 330,
zoom: 1,
pitch: 0
});
htmlMarker = new HTMLMarker(40.729952, -73.991056);
htmlMarker.setMap(map);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(40.729952, -73.991198),
map: map,
draggable: true,
title: 'My marker'
});
}
function toggleStreetView() {
var toggle = panorama.getVisible();
if (toggle == false) {
panorama.setVisible(true);
htmlMarker.setMap(null);
htmlMarker.setMap(panorama);
} else {
panorama.setVisible(false);
htmlMarker.setMap(null);
htmlMarker.setMap(map);
}
}
var button = document.getElementsByTagName('input')[0];
button.onclick = function() {
toggleStreetView()
};
#map-canvas {
height: 150px;
}
input {
margin: 10px;
background-color: #4CAF50;
border: none;
color: white;
padding: 4px 8px;
}
.html-marker {
background-color: red;
color: white;
line-height: 50px;
text-align: center;
font-size: 18px;
font-weight: bold;
}
<input type="button" value="Toggle Street View">
<div id="map-canvas"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize" async defer></script>
I have opened a new issue in the tracker. Let's see if this is a bug in the API, or an issue with the documentation (or both).
Fiddle showing how to do it: http://jsfiddle.net/upsidown/mLa4zvs7/
Fiddle showing that overlay sharing does not work by default: http://jsfiddle.net/upsidown/xsqvm6n0/

I am autoincrementing the value of an input element. I want to get the value

I am using the value of an input element as a measurement of the radius of a google maps circle. I want the value of the input element to increase every second and immediately use the value as the radius of the circle. I was sort of able to do this but I have to change the value myself for it to work. I want the radius of the circle to automatically increase.
Here is my code:
<!DOCTYPE html>
<html>
<head>
<style>
#map {
height: 400px;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="datetime">
Number: <input type="number" id="time" value="40">
</div>
<script>
function timeInterval() {
setInterval(function(){
document.getElementById("time").stepUp(10);
}, 1000);
}
window.onload = timeInterval;
function initMap() {
var annArbor = {lat: 42.271084, lng: -83.737277};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: annArbor
});
var circle = new google.maps.Circle( {
map : map,
center : annArbor,
radius : parseInt(document.getElementById("time").value),
editable : false,
strokeColor : '#FF0099',
strokeOpacity : 1,
strokeWeight : 2,
fillColor : '#009ee0',
fillOpacity : 0.2
} );
var time = document.getElementById('time');
time.addEventListener('input', function() {
circle.setRadius(parseInt(document.getElementById('time').value));
});
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
</body>
</html>
Just update circle on both input & interval.
<!DOCTYPE html>
<html>
<head>
<style>
#map {
height: 400px;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="datetime">
Number: <input type="number" id="time" value="40">
</div>
<script>
function timeInterval() {
setInterval(function(){
document.getElementById("time").stepUp(10);
setRadius()
}, 1000);
}
window.onload = timeInterval;
var circle;
function setRadius(){
circle.setRadius(parseInt(document.getElementById('time').value));
}
function initMap() {
var annArbor = {lat: 42.271084, lng: -83.737277};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: annArbor
});
circle = new google.maps.Circle( {
map : map,
center : annArbor,
radius : parseInt(document.getElementById("time").value),
editable : false,
strokeColor : '#FF0099',
strokeOpacity : 1,
strokeWeight : 2,
fillColor : '#009ee0',
fillOpacity : 0.2
} );
var time = document.getElementById('time');
time.addEventListener('input', setRadius);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?callback=initMap">
</script>
</body>
</html>

Google Maps API v3 - Directions with draggable alternate routes

I've successfully implemented google map direction service api : https://developers.google.com/maps/documentation/javascript/directions with 'draggble' option enabled. Is it possible to show all routes together if multiple routes are available between 2 locations?
The current code is similar to: https://developers.google.com/maps/documentation/javascript/examples/directions-draggable and I do have alternative routes available in response code as I've enabled provideRouteAlternatives: true.
I tried the solution provided in : How to display alternative route using google map api. But when I used that code, I found it draws multiple routes with independent markers. That is, if 4 routes are available, there will be 4 'A' locations and 4 'B' locations and while dragging - only one of them get selected. Please find the below screenshots.
Initial View:
After dragging initial locations (issue with duplicate locations)
I need to drag in such a way that, when the location A or B is dragged, there should not be any duplicates and alternate routes should be automatically shown.
My current code is as follows (API key not added here):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Draggable directions</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%;
float: left;
width: 63%;
height: 100%;
}
#right-panel {
float: right;
width: 34%;
height: 100%;
}
.panel {
height: 100%;
overflow: auto;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="right-panel">
<p>Total Distance: <span id="total"></span></p>
</div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: -24.345, lng: 134.46} // Australia.
});
var directionsService = new google.maps.DirectionsService;
var directionsDisplay = new google.maps.DirectionsRenderer({
draggable: true,
map: map,
panel: document.getElementById('right-panel')
});
directionsDisplay.addListener('directions_changed', function() {
computeTotalDistance(directionsDisplay.getDirections());
});
displayRoute('Rosedale, MD, USA', 'Savage, MD, USA', directionsService,
directionsDisplay);
}
function displayRoute(origin, destination, service, display) {
service.route({
origin: origin,
destination: destination,
travelMode: 'DRIVING',
avoidTolls: true,
provideRouteAlternatives: true,
}, function(response, status) {
if (status === 'OK') {
for (var i = 0, len = response.routes.length; i < len; i++) {
new google.maps.DirectionsRenderer({
map: map,
directions: response,
routeIndex: i,
draggable : true,
});
}
display.setDirections(response);
} else {
alert('Could not display directions due to: ' + status);
}
});
}
function computeTotalDistance(result) {
var total = 0;
var myroute = result.routes[0];
for (var i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000;
document.getElementById('total').innerHTML = total + ' km';
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=API-KEY&callback=initMap">
</script>
</body>
</html>
Please help me. Thanks in advance!
Each route you draw is editable and has a start and end marker which means that you will always be dragging one of the routes marker and not all at once. You could use the suppressMarkers option to remove markers from the alternate routes but that wouldn't change a lot to the behavior.
The problem is that as each route is separate, if you move the start or end location, you should redraw every route otherwise only one will update.
That said, if you edit a route (other than by changing its start or end location) you should not redraw your routes. If you update the start or end location you will of course then lose any route waypoint you added. Unless you do something about that... which sounds like a pain.
var directionsService = new google.maps.DirectionsService();
var map;
function initialize() {
var center = new google.maps.LatLng(0, 0);
var myOptions = {
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: center
}
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
var start = "Sadulpur, India";
var end = "New Delhi, India";
plotDirections(start, end);
}
function plotDirections(start, end) {
var method = 'DRIVING';
var request = {
origin: start,
destination: end,
travelMode: google.maps.DirectionsTravelMode[method],
provideRouteAlternatives: true
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var routes = response.routes;
var colors = ['red', 'green', 'blue', 'orange', 'yellow', 'black'];
var directionsDisplays = [];
// Reset the start and end variables to the actual coordinates
start = response.routes[0].legs[0].start_location;
end = response.routes[0].legs[0].end_location;
// Loop through each route
for (var i = 0; i < routes.length; i++) {
var directionsDisplay = new google.maps.DirectionsRenderer({
map: map,
directions: response,
routeIndex: i,
draggable: true,
polylineOptions: {
strokeColor: colors[i],
strokeWeight: 4,
strokeOpacity: .3
}
});
// Push the current renderer to an array
directionsDisplays.push(directionsDisplay);
// Listen for the directions_changed event for each route
google.maps.event.addListener(directionsDisplay, 'directions_changed', (function(directionsDisplay, i) {
return function() {
var directions = directionsDisplay.getDirections();
var new_start = directions.routes[0].legs[0].start_location;
var new_end = directions.routes[0].legs[0].end_location;
if ((new_start.toString() !== start.toString()) || (new_end.toString() !== end.toString())) {
// Remove every route from map
for (var j = 0; j < directionsDisplays.length; j++) {
directionsDisplays[j].setMap(null);
}
// Redraw routes with new start/end coordinates
plotDirections(new_start, new_end);
}
}
})(directionsDisplay, i)); // End listener
} // End route loop
}
});
}
initialize();
#map-canvas {
height: 180px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
JSFiddle demo

set start and end position in google roads API using javascript

I want to know if setting start and end location in the map while I'm retrieving coordinates and placeId through google roads API is possible or not? Because while I initialize Roads API by setting a custom coordinate like:
var mapOptions = {
zoom: 17,
center: {lat: -33.8667, lng: 151.1955}
};
its shows me a specific location in the map where the coordinate exists. But I want to initialize a map where I set a start and end location in the map and then start to use snapToRoads API to retrieve coordinates.
Ok, I have done a little bit digging and solved it by myself.
The Javascript Part:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=drawing,places"></script>
<!--Elevation JS
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>-->
<script>
//GOOGLE_API_KEY
var apiKey = 'GOOGLE_API_KEY';
alert("Provide GOOGLE API KEY");
var map;
var elevator;
var directionsDisplay;
var directionsService;
var drawingManager;
var placeIdArray = [];
var polylines = [];
var snappedCoordinates = [];
var initialLocation;
var siberia = new google.maps.LatLng(60, 105);
var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
var browserSupportFlag = new Boolean();
function initialize()
{
var mapOptions = {
zoom: 17,
center: {lat: -33.8667, lng: 151.1955}
};
directionsService = new google.maps.DirectionsService();
var polylineOptionsActual = new google.maps.Polyline({
strokeColor: '#FF0000',
strokeOpacity: 0.6,
strokeWeight: 2
});
directionsDisplay = new google.maps.DirectionsRenderer({polylineOptions: polylineOptionsActual});
map = new google.maps.Map(document.getElementById('map'), mapOptions);
directionsDisplay.setMap(map);
// Create an ElevationService
elevator = new google.maps.ElevationService();
// Adds a Places search box. Searching for a place will center the map on that
// location.
map.controls[google.maps.ControlPosition.RIGHT_TOP].push(
document.getElementById('bar'));
var autocomplete = new google.maps.places.Autocomplete(document.getElementById('autocStart'));
autocomplete.bindTo('bounds', map);
autocomplete.addListener('place_changed', function() {
var placeStart = autocomplete.getPlace();
//alert(placeStart.place_id);
document.getElementById("startPlaceId").value=placeStart.place_id;
});
var autocomplete1 = new google.maps.places.Autocomplete(document.getElementById('autocEnd'));
autocomplete1.bindTo('bounds', map);
autocomplete1.addListener('place_changed', function() {
var placeEnd = autocomplete1.getPlace();
//alert(placeEnd.place_id);
document.getElementById("endPlaceId").value=placeEnd.place_id;
});
// Enables the polyline drawing control. Click on the map to start drawing a
// polyline. Each click will add a new vertice. Double-click to stop drawing.
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYLINE,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYLINE
]
},
polylineOptions: {
strokeColor: '#696969',
strokeWeight: 2
}
});
drawingManager.setMap(map);
// Snap-to-road when the polyline is completed.
drawingManager.addListener('polylinecomplete', function(poly) {
var path = poly.getPath();
polylines.push(poly);
placeIdArray = [];
runSnapToRoad(path);
});
// Clear button. Click to remove all polylines.
$('#clear').click(function(ev) {
for (var i = 0; i < polylines.length; ++i) {
polylines[i].setMap(null);
}
polylines = [];
ev.preventDefault();
return false;
});
}
// Snap a user-created polyline to roads and draw the snapped path
function runSnapToRoad(path) {
var pathValues = [];
for (var i = 0; i < path.getLength(); i++) {
pathValues.push(path.getAt(i).toUrlValue());
}
$.get('https://roads.googleapis.com/v1/snapToRoads', {
interpolate: true,
key: apiKey,
path: pathValues.join('|')
}, function(data) {
processSnapToRoadResponse(data);
drawSnappedPolyline();
//getAndDrawSpeedLimits();
});
}
// Store snapped polyline returned by the snap-to-road method.
function processSnapToRoadResponse(data)
{
snappedCoordinates = [];
placeIdArray = [];
for (var i = 0; i < data.snappedPoints.length; i++)
{
var latlng = new google.maps.LatLng(
data.snappedPoints[i].location.latitude,
data.snappedPoints[i].location.longitude);
//getElevation(latlng);
snappedCoordinates.push(latlng);
placeIdArray.push(data.snappedPoints[i].placeId);
}
//get Altitude in meters
getElevation(snappedCoordinates);
document.getElementById("snappedCoordinatesArray").value=snappedCoordinates;
document.getElementById("snappedPaceIdArray").value=placeIdArray;
}
// Draws the snapped polyline (after processing snap-to-road response).
function drawSnappedPolyline() {
var snappedPolyline = new google.maps.Polyline({
path: snappedCoordinates,
strokeColor: 'black',
strokeWeight: 3
});
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
}
// Gets speed limits (for 100 segments at a time) and draws a polyline
// color-coded by speed limit. Must be called after processing snap-to-road
// response.
function getAndDrawSpeedLimits() {
for (var i = 0; i <= placeIdArray.length / 100; i++) {
// Ensure that no query exceeds the max 100 placeID limit.
var start = i * 100;
var end = Math.min((i + 1) * 100 - 1, placeIdArray.length);
drawSpeedLimits(start, end);
}
}
// Gets speed limits for a 100-segment path and draws a polyline color-coded by
// speed limit. Must be called after processing snap-to-road response.
function drawSpeedLimits(start, end) {
var placeIdQuery = '';
for (var i = start; i < end; i++) {
placeIdQuery += '&placeId=' + placeIdArray[i];
}
$.get('https://roads.googleapis.com/v1/speedLimits',
'key=' + apiKey + placeIdQuery,
function(speedData) {
processSpeedLimitResponse(speedData, start);
}
);
}
// Draw a polyline segment (up to 100 road segments) color-coded by speed limit.
function processSpeedLimitResponse(speedData, start) {
var end = start + speedData.speedLimits.length;
for (var i = 0; i < speedData.speedLimits.length - 1; i++) {
var speedLimit = speedData.speedLimits[i].speedLimit;
var color = getColorForSpeed(speedLimit);
// Take two points for a single-segment polyline.
var coords = snappedCoordinates.slice(start + i, start + i + 2);
var snappedPolyline = new google.maps.Polyline({
path: coords,
strokeColor: color,
strokeWeight: 6
});
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
//passDataToObjC();
}
}
function getColorForSpeed(speed_kph) {
if (speed_kph <= 40) {
return 'purple';
}
if (speed_kph <= 50) {
return 'blue';
}
if (speed_kph <= 60) {
return 'green';
}
if (speed_kph <= 80) {
return 'yellow';
}
if (speed_kph <= 100) {
return 'orange';
}
return 'red';
}
function getElevation(snappedCoordinatesArr)
{
var locations = [];
// Retrieve the latlng and push it on the array
for (var i = 0; i < snappedCoordinatesArr.length; i++)
{
locations.push(snappedCoordinatesArr[i]);
}
// Create a LocationElevationRequest object using the array's one value
var positionalRequest =
{
'locations': locations
}
//alert(positionalRequest);
// Initiate the location request
elevator.getElevationForLocations(positionalRequest, function(results, status)
{
if (status == google.maps.ElevationStatus.OK)
{
// Retrieve the first result
if (results)
{
var altitudeArr=[];
for(var j=0;j<results.length;j++)
{
altitudeArr.push(results[j].elevation);
}
document.getElementById("altitudeArray").value=altitudeArr;
document.getElementById("dataDisplay").style.display="block";
//alert(altitudeArr);
}
else
{
alert('No results found');
}
}
else
{
alert('Elevation service failed due to: ' + status);
}
});
}
function calcRoute()
{
var start = document.getElementById("autocStart").value;
var end = document.getElementById('autocEnd').value;
//alert(start);
var request = {
origin:start,
destination:end,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
$(window).load(initialize);
</script>
And The HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Roads API</title>
<style>
html, body, #map {
height: 100%;
margin: 0px;
padding: 0px
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
#bar {
width: 240px;
background-color: rgba(255, 255, 255, 0.75);
margin: 8px;
padding: 4px;
border-radius: 4px;
}
#autoc {
width: 98%;
box-sizing: border-box;
}
</style>
<body>
<div id="map"></div>
<div id="bar">
<form id="geodata-form" action="http://wayzme.sulavmart.com/map/savedata">
<div id="dataDisplay" style="display:none;">
CoordinatesArray:
<input type="text" id="snappedCoordinatesArray" />
AltitudeArray:
<input type="text" id="altitudeArray" />
PaceIdArray:
<input type="text" id="snappedPaceIdArray" />
<input type="hidden" id="startPlaceId" />
<input type="hidden" id="endPlaceId" />
</div>
<p class="auto">
<input type="text" id="autocStart" style="width:98% !important" name="start" />
</p>
<p class="auto">
<input type="text" id="autocEnd" style="width:98% !important" name="end"/>
</p>
<input type="button" value="Get Directions" onClick="calcRoute();">
</form>
<p><a id="clear" href="#">Click here</a> to clear map.</p>
</div>
</body>
</html>

Openlayers - display pacific markers popup using marker id and onclick event

I have the following code which addes 3 markers to the map along with there popup boxes what I want to do is have a list of location at bottom of page and using the id of the marker when click a place in the list it just make that places popup appear on the map.
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Open Street Map</title>
<style type="text/css">
body { font: normal 10pt Helvetica, Arial; }
#map { width: 100%; height: 100%; border: 0px; padding: 0px; }
</style>
<script src="lib/OpenLayers.js" type="text/javascript"></script>
<script type="text/javascript">
var iconSize = new OpenLayers.Size(21, 25);
var iconOffset = new OpenLayers.Pixel(-(iconSize.w / 2), -iconSize.h);
var icon = new OpenLayers.Icon("img/fourmarker.png",
iconSize, iconOffset);
var zoom, center, currentPopup, map, lyrMarkers;
var popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
"autoSize": true,
"minSize": new OpenLayers.Size(300, 50),
"maxSize": new OpenLayers.Size(500, 300),
"keepInMap": true
});
var bounds = new OpenLayers.Bounds();
function addMarker(id, lng, lat, info) {
var pt = new OpenLayers.LonLat(lng, lat)
.transform(new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject());
bounds.extend(pt);
var feature = new OpenLayers.Feature(lyrMarkers, pt);
feature.closeBox = true;
feature.popupClass = popupClass;
feature.data.popupContentHTML = info ;
feature.data.overflow = "auto";
var marker = new OpenLayers.Marker(pt, icon.clone());
var markerClick = function(evt) {
if (currentPopup != null && currentPopup.visible()) {
currentPopup.hide();
}
if (this.popup == null) {
this.popup = this.createPopup(this.closeBox);
map.addPopup(this.popup);
this.popup.show();
} else {
this.popup.toggle();
}
currentPopup = this.popup;
OpenLayers.Event.stop(evt);
};
marker.events.register("mousedown", feature, markerClick);
lyrMarkers.addMarker(marker);
}
function initMap() {
var options = {
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
units: "m",
numZoomLevels: 19,
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-0.13011, -0.13011, 51.51039, 51.51039)
};
map = new OpenLayers.Map("map", options);
map.addControl(new OpenLayers.Control.DragPan());
var lyrOsm = new OpenLayers.Layer.OSM();
map.addLayer(lyrOsm);
lyrMarkers = new OpenLayers.Layer.Markers("Markers");
map.addLayer(lyrMarkers);
//add marker on given coordinates
addMarker('1',-0.12519,51.51112 , '<b>Tescos</b><br/>Covent garden');
addMarker('2',-0.13264,51.50918 , '<b>Spar</b><br/>Leicester Square');
addMarker('3', -0.12498,51.50807 , '<b>M & S</b><br/>Embankment');
center = bounds.getCenterLonLat();
map.setCenter(center, map.getZoomForExtent(bounds) - 1);
zoom = map.getZoom();
}
</script>
</head>
<body onload="initMap()" style="margin:0; border:0; padding:0; width:1000px; height:500px;">
<div id="map"></div>
</body>
</html>
EXTRA INFORMATION
I am going to add a list to bottom of map like so:
<ul>
<li>location1</li>
<li>location2</li>
<li>location3</li>
</ul>
What i want to get working is when the user clicks so location1 alink then that relevent popup box will show and the other will be removed.
How would this be done.
This very fast example (modify addMarker function):
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Open Street Map</title>
<style type="text/css">
body { font: normal 10pt Helvetica, Arial; }
#map { width: 100%; height: 100%; border: 0px; padding: 0px; }
#list > div { background-color: #aaa; margin-top: 10px; }
</style>
<script src="http://openlayers.org/api/OpenLayers.js" type="text/javascript"> </script>
</head>
<body onload="initMap()" style="margin:0; border:0; padding:0; width:1000px; height:500px;">
<div id="map"></div>
<div id="list" style="width:100%; height: 100%"></div>
</body>
<script type="text/javascript">
var iconSize = new OpenLayers.Size(21, 25);
var iconOffset = new OpenLayers.Pixel(-(iconSize.w / 2), -iconSize.h);
var icon = new OpenLayers.Icon("img/fourmarker.png",
iconSize, iconOffset);
var list = document.getElementById('list');
var zoom, center, currentPopup, map, lyrMarkers;
var popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
"autoSize": true,
"minSize": new OpenLayers.Size(300, 50),
"maxSize": new OpenLayers.Size(500, 300),
"keepInMap": true
});
var bounds = new OpenLayers.Bounds();
function addMarker(id, lng, lat, info) {
var pt = new OpenLayers.LonLat(lng, lat)
.transform(new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject());
bounds.extend(pt);
var feature = new OpenLayers.Feature(lyrMarkers, pt);
feature.closeBox = true;
feature.popupClass = popupClass;
feature.data.popupContentHTML = info ;
feature.data.overflow = "auto";
var marker = new OpenLayers.Marker(pt, icon.clone());
var markerClick = function(evt) {
if (currentPopup != null && currentPopup.visible()) {
currentPopup.hide();
}
if (this.popup == null) {
this.popup = this.createPopup(this.closeBox);
map.addPopup(this.popup);
this.popup.show();
} else {
this.popup.toggle();
}
currentPopup = this.popup;
OpenLayers.Event.stop(evt);
};
marker.events.register("mousedown", feature, markerClick);
lyrMarkers.addMarker(marker);
// add items
var listItem = OpenLayers.Util.createDiv(this.id, null, null, null, 'relative', null);
listItem.innerHTML = info;
list.appendChild(listItem);
var callback = function(e) {
marker.events.triggerEvent('mousedown');
console.log(marker);
OpenLayers.Event.stop(e);
};
OpenLayers.Event.observe(listItem, "touchend", OpenLayers.Function.bindAsEventListener(callback, this));
OpenLayers.Event.observe(listItem, "click", OpenLayers.Function.bindAsEventListener(callback, this));
}
function initMap() {
var options = {
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
units: "m",
numZoomLevels: 19,
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-0.13011, -0.13011, 51.51039, 51.51039)
};
map = new OpenLayers.Map("map", options);
map.addControl(new OpenLayers.Control.DragPan());
var lyrOsm = new OpenLayers.Layer.OSM();
map.addLayer(lyrOsm);
lyrMarkers = new OpenLayers.Layer.Markers("Markers");
map.addLayer(lyrMarkers);
//add marker on given coordinates
addMarker('1',-0.12519,51.51112 , '<b>Tescos</b><br/>Covent garden');
addMarker('2',-0.13264,51.50918 , '<b>Spar</b><br/>Leicester Square');
addMarker('3', -0.12498,51.50807 , '<b>M & S</b><br/>Embankment');
center = bounds.getCenterLonLat();
map.setCenter(center, map.getZoomForExtent(bounds) - 1);
zoom = map.getZoom();
}
</script>
</html>

Categories

Resources