Save Latitude/Longitude of polygons With Google Maps V3 - google-api

for a service providers website I am using the code below (stole it from here) to display a map and draw areas each provider covers. How can i return and store the arrays of latitudes/longitudes of each shape i draw? i need to save it into database so later i can use for search queries when searching for providers within a certain area.
<script type="text/javascript">
var drawingManager;
var selectedShape;
var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
var selectedColor;
var colorButtons = {};
function clearSelection() {
if (selectedShape) {
selectedShape.setEditable(false);
selectedShape = null;
}
}
function setSelection(shape) {
clearSelection();
selectedShape = shape;
shape.setEditable(true);
selectColor(shape.get('fillColor') || shape.get('strokeColor'));
}
function deleteSelectedShape() {
if (selectedShape) {
selectedShape.setMap(null);
}
}
function selectColor(color) {
selectedColor = color;
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
}
// Retrieves the current options from the drawing manager and replaces the
// stroke or fill color as appropriate.
var polylineOptions = drawingManager.get('polylineOptions');
polylineOptions.strokeColor = color;
drawingManager.set('polylineOptions', polylineOptions);
var rectangleOptions = drawingManager.get('rectangleOptions');
rectangleOptions.fillColor = color;
drawingManager.set('rectangleOptions', rectangleOptions);
var circleOptions = drawingManager.get('circleOptions');
circleOptions.fillColor = color;
drawingManager.set('circleOptions', circleOptions);
var polygonOptions = drawingManager.get('polygonOptions');
polygonOptions.fillColor = color;
drawingManager.set('polygonOptions', polygonOptions);
}
function setSelectedShapeColor(color) {
if (selectedShape) {
if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE) {
selectedShape.set('strokeColor', color);
} else {
selectedShape.set('fillColor', color);
}
}
}
function makeColorButton(color) {
var button = document.createElement('span');
button.className = 'color-button';
button.style.backgroundColor = color;
google.maps.event.addDomListener(button, 'click', function() {
selectColor(color);
setSelectedShapeColor(color);
});
return button;
}
function buildColorPalette() {
var colorPalette = document.getElementById('color-palette');
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
var colorButton = makeColorButton(currColor);
colorPalette.appendChild(colorButton);
colorButtons[currColor] = colorButton;
}
selectColor(colors[0]);
}
function initialize() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng(22.344, 114.048),
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true,
zoomControl: true
});
var polyOptions = {
strokeWeight: 0,
fillOpacity: 0.45,
editable: true
};
// Creates a drawing manager attached to the map that allows the user to draw
// markers, lines, and shapes.
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
markerOptions: {
draggable: true
},
polylineOptions: {
editable: true
},
rectangleOptions: polyOptions,
circleOptions: polyOptions,
polygonOptions: polyOptions,
map: map
});
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
if (e.type != google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
var newShape = e.overlay;
newShape.type = e.type;
google.maps.event.addListener(newShape, 'click', function() {
setSelection(newShape);
});
setSelection(newShape);
}
});
// Clear the current selection when the drawing mode is changed, or when the
// map is clicked.
google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
google.maps.event.addListener(map, 'click', clearSelection);
google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);
buildColorPalette();
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
any help would be appreciated.
Thank you

This is something you need.
I tested it and it works very well.
Just copy and then enjoy it.
<html>
<!--Here you will create a polygon by tools that Google maps "drawingManager" gives to you and then you have an array named "coordinates" as an output. This array saves all latLng of the polygon. When you edit the polygon it also edit this variable too.
!-->
<head>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&libraries=drawing"></script>
<!--Global variables!-->
<script>
//This variable gets all coordinates of polygone and save them. Finally you should use this array because it contains all latitude and longitude coordinates of polygon.
var coordinates = [];
//This variable saves polygon.
var polygons = [];
</script>
<script>
//This function save latitude and longitude to the polygons[] variable after we call it.
function save_coordinates_to_array(polygon)
{
//Save polygon to 'polygons[]' array to get its coordinate.
polygons.push(polygon);
//This variable gets all bounds of polygon.
var polygonBounds = polygon.getPath();
for(var i = 0 ; i < polygonBounds.length ; i++)
{
coordinates.push(polygonBounds.getAt(i).lat(), polygonBounds.getAt(i).lng());
alert(i);
}
}
</script>
<script>
function initialize()
{
//Create a Google maps.
var map = new google.maps.Map(document.getElementById('map'), {zoom: 12, center: new google.maps.LatLng(32.344, 51.048)});
//Create a drawing manager panel that lets you select polygon, polyline, circle, rectangle or etc and then draw it.
var drawingManager = new google.maps.drawing.DrawingManager();
drawingManager.setMap(map);
//This event fires when creation of polygon is completed by user.
google.maps.event.addDomListener(drawingManager, 'polygoncomplete', function(polygon) {
//This line make it possible to edit polygon you have drawed.
polygon.setEditable(true);
//Call function to pass polygon as parameter to save its coordinated to an array.
save_coordinates_to_array(polygon);
//This event is inside 'polygoncomplete' and fires when you edit the polygon by moving one of its anchors.
google.maps.event.addListener(polygon.getPath(), 'set_at', function () {
alert('changed');
save_coordinates_to_array(polygon);
});
//This event is inside 'polygoncomplete' too and fires when you edit the polygon by moving on one of its anchors.
google.maps.event.addListener(polygon.getPath(), 'insert_at', function () {
alert('also changed');
save_coordinates_to_array(polygon);
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div style="width:1024px; height:768px;" id="map"></div>
</body>
</html>

Related

How to show a color-coded country map (with city boundaries) in Aframe

Following my previous question:Load json map into aframe by aframe-geo-projection-component created by earthlinginteractive
Now, I am trying to find a way to show different geometries (country or city) in AFrame each with a different color,
looking for something like this.
I do not mind which library or approach are used, Found this but not sure how to convert this D3.js to Aframe. However as the community bot asked me to provide more details, I have put the code that I am working on below. Not sure which part I need to modify to have such a color coded map but I am working on that. Again, any working example works for me even if someone can show what I need to modify in the below code.
<!-- https://github.com/EarthlingInteractive/aframe-geo-projection-component
https://earthlinginteractive.github.io/aframe-geo-projection-component/ -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>A-Frame Geo Projection Component - U.S. Population 2017 (est.)</title>
<meta name="description" content="Visualization of estimated U.S. population by state in 2017"></meta>
<script src="https://aframe.io/releases/0.7.1/aframe.min.js"></script>
<script src="//cdn.rawgit.com/donmccurdy/aframe-extras/v3.12.4/dist/aframe-extras.min.js"></script>
<script src="https://unpkg.com/super-hands#2.1.0/dist/super-hands.min.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script src="https://d3js.org/d3-queue.v3.js"></script>
<script src="https://earthlinginteractive.github.io/aframe-geo-projection-component/dist/aframe-geo-projection-component.min.js"></script>
</head>
<body>
<script>
AFRAME.registerComponent('geo-extrude-population-renderer', {
dependencies: ['geo-projection'],
schema: {
maxExtrudeHeight: {
default: 2
}
},
init: function () {
this.system = this.el.sceneEl.systems['geo-projection'];
this.geoProjectionComponent = this.el.components['geo-projection'];
this.geoJsonReady = this.geoJsonReady.bind(this);
// Wait for geoJson to finish loading to avoid race conditions
this.el.addEventListener('geo-src-loaded', this.geoJsonReady);
},
update: function (oldData) {
if (!this.geoProjectionComponent.geoJson) {
return;
}
if (this.data.maxExtrudeHeight !== oldData.maxExtrudeHeight) {
this.geoJsonReady();
}
},
geoJsonReady: function () {
// Now kick off loading the data
d3.queue()
.defer(d3.csv, 'https://cdn.glitch.global/c153e3cf-7430-444d-9897-4e97f1ef8d35/us-population-2017.csv?v=1657704183925', function (d) {
return {
state: d.state,
population: +d.population
}
})
.defer(d3.csv, 'https://cdn.glitch.global/c153e3cf-7430-444d-9897-4e97f1ef8d35/us-state-county-geocodes-v2016.csv?v=1657704190160')
.await(this.onDataLoaded.bind(this));
},
onDataLoaded: function(error, populationData, geocodes) {
if (error) throw error;
var stateFips = geocodes.filter(function (row) {
return row['Summary_Level'] === '040'
});
var maxPopulation = d3.max(populationData, function (d) {
return d.population;
});
var populationByFipsCode = populationData.reduce(function (accum, d) {
var fipsForState = stateFips.find(function (fipsRow) { return fipsRow['Area_Name'] === d.state; });
var fipsCode = fipsForState['State_Code_FIPS'];
accum[fipsCode] = d.population;
return accum;
}, {});
this.render(populationByFipsCode, maxPopulation, this.data.maxExtrudeHeight);
},
render: function (populationByFipsCode, maxPopulation, maxExtrudeHeight) {
if (!populationByFipsCode) return;
var material = [];
var extrudeGeometry = null;
var stateOutlineVertices = [];
// Split the geoJson into features and render each one individually so that we can set a different
// extrusion height for each based on the population.
this.geoProjectionComponent.geoJson.features.forEach(function (feature) {
var population = populationByFipsCode[feature.id];
var extrudeAmount = (population / maxPopulation) * maxExtrudeHeight;
var material="#999999";
const extrudeSettings = {
amount: extrudeAmount,
bevelEnabled: false
};
//Math.floor(Math.random()*16777215).toString(16);
var mapRenderContext = this.system.renderToContext(feature, this.geoProjectionComponent.projection);
const stateShapes = mapRenderContext.toShapes();
// Gather the outline of the state and set the height of the outline to the extrude level
// so that the top of the state is outlined
stateOutlineVertices = stateOutlineVertices.concat(mapRenderContext.toVertices(extrudeAmount));
// Merge all the extruded feature geometries together for better rendering performance
// Need to use ExtrudeGeometry here instead of ExtrudeBufferGeometry because the latter doesn't merge properly
// in this version of Three.js
var extrudedFeatureGeometry = new THREE.ExtrudeGeometry(stateShapes, extrudeSettings);
if (!extrudeGeometry) {
extrudeGeometry = extrudedFeatureGeometry;
} else {
extrudeGeometry.merge(extrudedFeatureGeometry);
}
}.bind(this));
// Convert the extrude geometry into a buffer geometry for better rendering performance
var extrudeBufferGeometry = new THREE.BufferGeometry();
extrudeBufferGeometry.fromGeometry(extrudeGeometry);
var sideMaterial = new THREE.MeshStandardMaterial( { color: 0xaaafff } );
var extrudedMap = new THREE.Mesh(extrudeBufferGeometry, [material, sideMaterial]);
this.el.setObject3D('map', extrudedMap);
var stateOutlineGeometry = new THREE.BufferGeometry();
stateOutlineGeometry.addAttribute('position', new THREE.Float32BufferAttribute(stateOutlineVertices, 3));
var stateOutlineMaterial = new THREE.LineBasicMaterial( { color: 0xcccaaa } );
var stateOutlines = new THREE.LineSegments(stateOutlineGeometry, stateOutlineMaterial);
this.el.setObject3D('lines', stateOutlines);
}
});
</script>
<a-scene>
<a-assets>
<a-asset-item id="json-us" src="https://unpkg.com/us-atlas#1/us/10m.json" />
</a-assets>
<a-sky color="#ECECEC"></a-sky>
<a-entity id="map"
rotation="-90 0 0"
material="color: #123456;"
topojson-loader="src: #json-us; topologyObject: states;"
geo-projection="
projection: geoIdentity;
height: 6;
width: 10;"
geo-extrude-population-renderer
>
</a-entity>
<a-locomotor>
<a-entity hand-controls="left" super-hands></a-entity>
<a-entity hand-controls="right" super-hands></a-entity>
</a-locomotor>
</a-scene>
</body>
</html>
<!--material="color: #123456;"-->
getting this error as well if I use aframe 1.3.0:
Uncaught TypeError: extrudeBufferGeometry.fromGeometry is not a function
at i.render ((index):104:29)
at i.onDataLoaded ((index):66:12)
at Queue._call (d3-queue.v3.js:43:54)
at maybeNotify (d3-queue.v3.js:120:7)
at d3-queue.v3.js:91:12
at Object.<anonymous> (d3.v4.js:11470:86)
at Dispatch.call (d3.v4.js:792:72)
at XMLHttpRequest.respond (d3.v4.js:11395:13)

Using Geolocation within Google Places API

I'm simply trying to replace the lat long coords to use the browsers geolocation yet I'm getting no result...
Code for the geolocation is;
<script> var coords = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
function initAutocomplete() {
var map = new google.maps.Map(document.getElementById('map'), {
center: coords,
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
The rest of the code points to the simple places api service;
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function() {
searchBox.setBounds(map.getBounds());
});
var markers = [];
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function() {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
markers.forEach(function(marker) {
marker.setMap(null);
});
markers = [];
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
icon: icon,
title: place.name,
position: place.geometry.location
}));
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(success);
} else {
error('Geo Location is not supported');
}
</script>
I cannot for the life of me find any reliable tutorials on-line...

google map api not working for ajax from 2nd response onwards

In my application i have to show the path covered by an user in particulat date working fine for first response,from second response from ajax i am getting data which is diffrent from first one but still map showing 1st response result
I included google map javascript api like below in header section of html
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
I am using following code in my jsp file
<script>
$(document).ready(function(){
window.setInterval(positionCheck, 20000);
});
</script>
<script>
$(document).ready(function(){
document.getElementById("directions_panel").innerHTML = "";
document.getElementById("map").innerHTML = "";
$("#searchSubmit").onclick(){
positionCheck();
}
});
</script>
<script type="text/javascript">
function positionCheck(){
var username=$("#xmlLabel").val();
var searchDate=$("#searchDate").val();
if(username!=""&& searchDate!=''){
This part where i used ajax call working fine for first response
from second response onwards problem arises it is showing content of first response from server
$.ajax({
type : "POST",
url : "searchLocation.mnt",
data :"xmlLabel="+username+"&searchDate="+searchDate,
dataType : "json",
mimeType : 'application/json',
success : function(data) {
if(data!=""){
mapLoaded(data);
function mapLoaded(data){
var size=0;
var counts=0;
var stops = data;
alert(stops);
size =stops.length;
if(stops.length>0){
var mapid=document.getElementById("map");
var map = new window.google.maps.Map(mapid);
// new up complex objects before passing them around
var directionsDisplay = new window.google.maps.DirectionsRenderer({suppressMarkers: true,polylineOptions: {
strokeColor: "black"
}});
var directionsService = new window.google.maps.DirectionsService();
Tour_startUp(stops);
window.tour.loadMap(map, directionsDisplay);
window.tour.fitBounds(map);
alert(stops.length);
if (stops.length > 1)
window.tour.calcRoute(directionsService, directionsDisplay);
}
alert(stops.length);
function Tour_startUp(stops) {
if (!window.tour) window.tour = {
updateStops: function (newStops) {
stops = newStops;
},
// map: google map object
// directionsDisplay: google directionsDisplay object (comes in empty)
loadMap: function (map, directionsDisplay) {
var myOptions = {
zoom:4,
center: new window.google.maps.LatLng(17.379818, 78.478542), // default to Hyderabad
mapTypeId: window.google.maps.MapTypeId.ROADMAP
};
map.setOptions(myOptions);
directionsDisplay.setMap(map);
},
fitBounds: function (map) {
var bounds = new window.google.maps.LatLngBounds();
// extend bounds for each record
jQuery.each(stops, function (key, val) {
var myLatlng = new window.google.maps.LatLng(val.latitude, val.longitude);
bounds.extend(myLatlng);
});
map.fitBounds(bounds);
},
calcRoute: function (directionsService, directionsDisplay) {
var batches = [];
var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
var itemsCounter = 0;
var wayptsExist = stops.length > 0;
while (wayptsExist) {
var subBatch = [];
var subitemsCounter = 0;
for (var j = itemsCounter; j < stops.length; j++) {
subitemsCounter++;
subBatch.push({
location: new window.google.maps.LatLng(stops[j].latitude, stops[j].longitude),
stopover: true
});
if (subitemsCounter == itemsPerBatch)
break;
}
itemsCounter += subitemsCounter;
batches.push(subBatch);
wayptsExist = itemsCounter < stops.length;
// If it runs again there are still points. Minus 1 before continuing to
// start up with end of previous tour leg
itemsCounter--;
}
// now we should have a 2 dimensional array with a list of a list of waypoints
var combinedResults;
var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
var directionsResultsReturned = 0;
for (var k = 0; k < batches.length; k++) {
var lastIndex = batches[k].length - 1;
var start = batches[k][0].location;
var end = batches[k][lastIndex].location;
// trim first and last entry from array
var waypts = [];
waypts = batches[k];
waypts.splice(0, 1);
waypts.splice(waypts.length - 1, 1);
var request = {
origin: start,
destination: end,
waypoints: waypts,
travelMode: window.google.maps.TravelMode.WALKING
};
(function (kk) {
directionsService.route(request, function (result, status) {
if (status == window.google.maps.DirectionsStatus.OK) {
var unsortedResult = { order: kk, result: result };
unsortedResults.push(unsortedResult);
directionsResultsReturned++;
if (directionsResultsReturned == batches.length) // we've received all the results. put to map
{
// sort the returned values into their correct order
unsortedResults.sort(function (a, b) { return parseFloat(a.order) - parseFloat(b.order); });
var count = 0;
for (var key in unsortedResults) {
if (unsortedResults[key].result != null) {
if (unsortedResults.hasOwnProperty(key)) {
if (count == 0) // first results. new up the combinedResults object
combinedResults = unsortedResults[key].result;
else {
// only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
// directionResults object, but enough to draw a path on the map, which is all I need
combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
}
count++;
}
}
}
directionsDisplay.setDirections(combinedResults);
var legs = combinedResults.routes[0].legs;
var summaryPanel = document.getElementById('directions_panel');
summaryPanel.innerHTML = '';
var totdist=0;
// alert(legs.length);
for (var i=0; i < legs.length;i++){
var markerletter = "A".charCodeAt(0);
var markerletter2= "B".charCodeAt(0)
markerletter += i;
markerletter2 += i;
markerletter = String.fromCharCode(markerletter);
markerletter2 = String.fromCharCode(markerletter2);
createMarker(directionsDisplay.getMap(),legs[i].start_location,legs[i].start_address,markerletter);//To display location address on the marker
var routeSegment = i + 1;
var point=+routeSegment+1;
summaryPanel.innerHTML += '<b>Route Segment: ' + routeSegment + '</b><br>';
summaryPanel.innerHTML += '<b>Point '+ routeSegment +' :</b>'+ ' ' +legs[i].start_address + ' <br> ';
summaryPanel.innerHTML += '<b>Point '+ point +' :</b>'+ ' '+legs[i].end_address + '<br>';
summaryPanel.innerHTML += '<b>Distance Covered '+' :</b>'+legs[i].distance.text + '<br><br>';
var test=legs[i].distance.text.split(' ');
var one=parseFloat(test[0]);
if(test[1]=="m"){
var one=parseFloat(test[0]/1000);
}
totdist=parseFloat(totdist)+parseFloat(one);
}
summaryPanel.innerHTML += '<b> Total Distance :'+totdist + 'km'+ '</b><br><br>';
var i=legs.length;
var markerletter = "A".charCodeAt(0);
markerletter += i;
markerletter = String.fromCharCode(markerletter);
createMarker(directionsDisplay.getMap(),legs[legs.length-1].end_location,legs[legs.length-1].end_address,markerletter);
}
}
});
})(k);
}
}
};
}
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
var icons = new Array();
icons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
function getMarkerImage(iconStr) {
counts++;
if(counts==size){
var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/blue.png";
}else{
if (iconStr=="undefined") {
iconStr = "red";
var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/red.png";
}
else{
var markerimageLoc="http://www.google.com/mapfiles/marker"+ iconStr +".png";
// var markerimageLoc = "http://www.maps.google.com/mapfiles/ms/icons/red.png";
}
}
icons[iconStr] = new google.maps.MarkerImage(markerimageLoc,
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(25, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 6,20.
new google.maps.Point(9, 34));
return icons[iconStr];
}
// Marker sizes are expressed as a Size of X,Y
// where the origin of the image (0,0) is located
// in the top left of the image.
// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.
var iconImage = new google.maps.MarkerImage('mapIcons/marker_red.png',
// This marker is 20 pixels wide by 34 pixels tall.
new google.maps.Size(20, 34),
// The origin for this image is 0,0.
new google.maps.Point(0,0),
// The anchor for this image is at 9,34.
new google.maps.Point(9, 34));
var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
// The shadow image is larger in the horizontal dimension
// while the position and offset are the same as for the main image.
new google.maps.Size(37, 34),
new google.maps.Point(0,0),
new google.maps.Point(9, 34));
// Shapes define the clickable region of the icon.
// The type defines an HTML <area> element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var iconShape = {
coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0],
type: 'poly'
};
function createMarker(map, latlng, label, character) {
var markerletter=character;
if( /[^a-zA-Z]/.test( character ) ) {
var markerletter="undefined";
}
var contentString = '<b>'+label+'</b><br>';
var marker = new google.maps.Marker({
position: latlng,
map: map,
shadow: iconShadow,
icon: getMarkerImage(markerletter),
shape: iconShape,
title: label,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
marker.myname = label;
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
return marker;
}
}
}else{
}
},
error : function(e) {
alert('Error: ' + e,"Alert Box");
}
});
}
}
</script>
and i included div tag like this in body section
<div id="map" style="border: 2px solid #3872ac; height: 500px;"
class="col-sm-6"></div>
above code working fine if i am not using ajax,problem exist only for ajax
sorry to trouble all of you,i feel very silly that i declared variable of stops globally and i need to call methods like below
function initialize(data) {
size = 0;
counts = 0;
var map=0;
var stops = data;
size = stops.length;
if (stops.length > 0) {
var map = new window.google.maps.Map(document
.getElementById("map"));
// new up complex objects before passing them around
var directionsDisplay = new window.google.maps.DirectionsRenderer(
{
suppressMarkers : true,
polylineOptions : {
strokeColor : "black"
}
});
var directionsService = new window.google.maps.DirectionsService();
Tour_startUp(stops);
window.tour.loadMap(map, directionsDisplay);
i changed the below methods from window.tour.fitBounds(map); window.tour.calcRoute(stops,directionsService,
directionsDisplay); to
window.tour.fitBounds(map,stops);
if (stops.length > 1)
window.tour.calcRoute(stops,directionsService,
directionsDisplay);
}
}

OpenLayers3 : Draggable OverviewMapControl

In OpenLayers 2, in the OverviewMapControl, you can drag the "box" to move the map.
You can not do this in OpenLayers 3.
I've tried to implement a custom control based on https://github.com/openlayers/ol3/blob/master/src/ol/control/overviewmapcontrol.js, but you can not use goog.xxx or other fancy stuff like ol.extent.scaleFromCenter when you are not in debug !
How should I proceed ?
basically, implementing drag'n drop is fairly "simple" :
var dragging = null;
var getMap = this.getMap.bind(this); //during ctor of a control, we have no access to the map !
$(document.body).on("mousemove", function (e) {
if (dragging) {
dragging.el.offset({
top: e.pageY,
left: e.pageX
});
}
});
$(box).on("mousedown", function (e) {
dragging = {
el: $(e.target)
};
});
$(document.body).on("mouseup", function (e) {
if (dragging) {
debugger;
var coords = ovmap.getEventCoordinate(e.originalEvent);
//TODO: taking event coordinates is not good, we must use center of the box coordinates
//the problem is that ovmap.getCoordinateFromPixel(dragging.el.offset()) is not working at all because we need to adjust ovmap viewport
getMap().getView().setCenter(coords);
dragging = null;
}
});
For those interested (which does not seem to be the case at the moment :)), here is the way I solved
/**
* Mostly a big copy/paste from https://raw.githubusercontent.com/openlayers/ol3/master/src/ol/control/overviewmapcontrol.js
* without rotation and zoom/dezoom plus some adapations from http://ol3.qtibia.ro/build/examples/overviewmap-custom-drag.html
* to add the possibility to drag the box on the minimap to move the main map
*/
ol.control.CustomOverviewMap = function (opt_options) {
var options = typeof opt_options !== 'undefined' ? opt_options : {};
this.collapsed_ = typeof options.collapsed !== 'undefined' ? options.collapsed : true;
this.onCollapseOrExpand = options.onCollapseOrExpand || function () { };
this.needFirstRenderUpdate_ = this.collapsed_; //prepare the hack to render the map when uncollapsed the first time
var tipLabel = typeof options.tipLabel !== 'undefined' ? options.tipLabel : 'Overview map';
this.collapseLabel_ = $('<span>\u00BB</span>').get(0);
this.label_ = $('<span>\u00AB</span>').get(0);
var activeLabel = (!this.collapsed_) ? this.collapseLabel_ : this.label_;
var button = $('<button type="button" title="{0}"></button>'.replace('{0}', tipLabel)).append(activeLabel);
button.on('click', this.handleClick_.bind(this));
//ol.control.Control.bindMouseOutFocusOutBlur(button);
button.on('mouseout', function () { this.blur(); });
button.on('focusout', function () { this.blur(); });
var ovmapDiv = $('<div class="ol-overviewmap-map"></div>').get(0);
this.ovmap_ = new ol.Map({
controls: new ol.Collection(),
interactions: new ol.Collection(),
layers: [options.tileLayer],
target: ovmapDiv,
view: new ol.View(opt_options.view)
});
var box = $('<div class="ol-overviewmap-box"></div>');
this.boxOverlay_ = new ol.Overlay({
position: [0, 0],
positioning: 'bottom-left',
element: box.get(0)
});
this.ovmap_.addOverlay(this.boxOverlay_);
var cssClasses = 'ol-overviewmap ol-unselectable ol-control' +
(this.collapsed_ ? ' ol-collapsed' : '');
var element = $('<div class="{0}"></div>'.replace('{0}', cssClasses)).append(ovmapDiv).append(button).get(0);
ol.control.Control.call(this, {
element: element,
render: ol.control.CustomOverviewMap.render
});
// deal with dragable minimap
this.dragging = null;
box.on("mousedown", this.onStartDrag.bind(this));
$(document.body).on("mousemove", this.onDrag.bind(this));
$(document.body).on("mouseup", this.onEndDrag.bind(this));
};
ol.inherits(ol.control.CustomOverviewMap, ol.control.Control);
ol.control.CustomOverviewMap.prototype.onStartDrag = function (e) {
// remember some data to use during onDrag or onDragEnd
var box = $(e.target);
this.dragging = {
el: box,
evPos: { top: e.pageY, left: e.pageX },
elPos: box.offset()
};
}
ol.control.CustomOverviewMap.prototype.onDrag = function (e) {
if (this.dragging) {
//set the position of the box to be oldPos+translation(ev)
var curOffset = this.dragging.el.offset();
var newOffset = {
top: curOffset.top + (e.pageY - this.dragging.evPos.top),
left: curOffset.left + (e.pageX - this.dragging.evPos.left)
};
this.dragging.evPos = { top: e.pageY, left: e.pageX };
this.dragging.el.offset(newOffset);
}
}
ol.control.CustomOverviewMap.prototype.onEndDrag = function (e) {
if (this.dragging) {
//see ol3.qtibia.ro href at the top of the class to understand this
var map = this.getMap();
var offset = this.dragging.el.position();
var divSize = [this.dragging.el.width(), this.dragging.el.height()];
var mapSize = map.getSize();
var c = map.getView().getResolution();
var xMove = offset.left * (Math.abs(mapSize[0] / divSize[0]));
var yMove = offset.top * (Math.abs(mapSize[1] / divSize[1]));
var bottomLeft = [0 + xMove, mapSize[1] + yMove];
var topRight = [mapSize[0] + xMove, 0 + yMove];
var left = map.getCoordinateFromPixel(bottomLeft);
var top = map.getCoordinateFromPixel(topRight);
var extent = [left[0], left[1], top[0], top[1]];
map.getView().fitExtent(extent, map.getSize());
map.getView().setResolution(c);
//reset the element at the original position so that when the main map will trigger
//the moveend event, this event will be replayed on the box of the minimap
this.dragging.el.offset(this.dragging.elPos);
this.dragging = null;
}
}
ol.control.CustomOverviewMap.render = function (mapEvent) {
//see original OverviewMap href at the top of the class to understand this
var map = this.getMap();
var ovmap = this.ovmap_;
var mapSize = map.getSize();
var view = map.getView();
var ovview = ovmap.getView();
var overlay = this.boxOverlay_;
var box = this.boxOverlay_.getElement();
var extent = view.calculateExtent(mapSize);
var ovresolution = ovview.getResolution();
var bottomLeft = ol.extent.getBottomLeft(extent);
var topRight = ol.extent.getTopRight(extent);
overlay.setPosition(bottomLeft);
// set box size calculated from map extent size and overview map resolution
if (box) {
var boxWidth = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution);
var boxHeight = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution);
$(box).width(boxWidth).height(boxHeight);
}
};
ol.control.CustomOverviewMap.prototype.handleClick_ = function (event) {
event.preventDefault();
this.collapsed_ = !this.collapsed_;
$(this.element).toggleClass('ol-collapsed');
// change label
if (this.collapsed_) {
this.collapseLabel_.parentNode.replaceChild(this.label_, this.collapseLabel_);
} else {
this.label_.parentNode.replaceChild(this.collapseLabel_, this.label_);
}
// manage overview map if it had not been rendered before and control is expanded
if (!this.collapsed_ && this.needFirstRenderUpdate_) {
this.needFirstRenderUpdate_ = false;
this.ovmap_.updateSize();
this.ovmap_.once("postrender", function () {
this.render();
}.bind(this));
}
//trigger event
this.onCollapseOrExpand(this.collapsed_);
};

How to get Famo.us draggable modifier's render node

I am trying to get parent renderNode of a draggable modifier on 'end' event, is there any api to get a renderNode to which draggable belongs to? My code is as follows :
/*globals define*/
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Draggable = require("famous/modifiers/Draggable");
var RenderNode = require('famous/core/RenderNode');
/*
* #name DragTest
* #constructor
* #description
*/
function DragTest() {
View.apply(this, arguments);
_createDragSurface.call(this);
}
DragTest.prototype = Object.create(View.prototype);
DragTest.prototype.constructor = DragTest;
DragTest.DEFAULT_OPTIONS = {
};
function _createDragSurface(){
var yOffset=0;
for(var i=0;i<2;i++){
var draggable = new Draggable({
xRange: [-220,0],
yRange: [0,0]
});
var dragSurface= new Surface({
content:'this is a drag surface',
size:[150,150],
properties:{
marginLeft: '10px',
backgroundColor:'grey'
}
});
var dragSurfaceModifier= new StateModifier({
align:[0.5,yOffset]
});
yOffset+=0.3;
dragSurface.pipe(draggable);
draggable.on('end',function(e){
this.setPosition([0,0,0], {
method: 'snap',
period: 300
});
});
var nodePlayer = new RenderNode(draggable);
nodePlayer.add(dragSurfaceModifier).add(dragSurface);
this.add(nodePlayer);
}
}
module.exports = DragTest;
});
On drag of a surface to the left, once it reaches threshold, I want to remove the renderNode i.e.,
draggable.on('end',function(e){
if(e.position[0]<-50){
renderNode.remove()//how to achieve this part of the code as I dont have an access to nodePlayer renderNode here.
}
else{
this.setPosition([0,0,0], {
method: 'snap',
period: 300
});
}
});
If I simply use the name of a renderNode i.e., nodePlayer it will remove the last surface no matter which surface is been dragged.Any input on this is much appreciated.
Best Regards.
There are a lot of ways to accomplish what you want to do.
Since you are using the end event on the draggable and using the position value from the custom event, let's bind the references to the needed items to be able to access them.
There is not a .remove() method on the RenderNode so the example shows a way you could remove a node from the view with a RenderController.
Remember: There is no need to remove nodes from the DOM. Famo.us will manage the renderables in the render tree.
define('main', function(require, exports, module) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var Modifier = require('famous/core/Modifier');
var StateModifier = require('famous/modifiers/StateModifier');
var Draggable = require('famous/modifiers/Draggable');
var TransitionableTransform = require('famous/transitions/TransitionableTransform');
var DragTest = require('DragTest');
var mainContext = Engine.createContext();
var dragTest = new DragTest();
mainContext.add(dragTest);
dragTest.on('removed', function(e) {
console.log('removed ', e.removedNode);
});
});
define('DragTest', function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Draggable = require("famous/modifiers/Draggable");
var RenderNode = require('famous/core/RenderNode');
var RenderController = require('famous/views/RenderController');
/*
* #name DragTest
* #constructor
* #description
*/
function DragTest() {
View.apply(this, arguments);
_createDragSurface.call(this);
}
DragTest.prototype = Object.create(View.prototype);
DragTest.prototype.constructor = DragTest;
DragTest.DEFAULT_OPTIONS = {};
function _endingDrag(e) {
console.log('end position', e.position, this);
if (e.position[0] < -180) {
this.renderController.hide(this.nodePlayer, function() {
this.surface.emit('removed', {
removedNode: this.nodePlayer
});
}.bind(this));
} else {
this.draggable.setPosition([0, 0, 0], {
duration: 300
});
}
}
function _updatingDrag(e) {
console.log('update position', e.position);
this.surface.setContent('Position ' + e.position);
}
function _createDragSurface() {
var yOffset = 0;
for (var i = 0; i < 2; i++) {
var dragSurface = new Surface({
content: 'this is a drag surface',
size: [150, 150],
properties: {
marginLeft: '10px',
backgroundColor: 'grey'
}
});
var dragSurfaceModifier = new StateModifier({
origin: [0, 0],
align: [0.5, yOffset]
});
yOffset += 0.3;
var draggable = new Draggable({
xRange: [-220, 0],
yRange: [0, 0]
});
var renderController = new RenderController();
this.add(renderController);
var nodePlayer = new RenderNode();
nodePlayer.add(dragSurfaceModifier).add(draggable).add(dragSurface);
renderController.show(nodePlayer)
draggable.on('end', _endingDrag.bind({
draggable: draggable,
renderController: renderController,
nodePlayer: nodePlayer,
surface: dragSurface
}));
draggable.on('update', _updatingDrag.bind({
surface: dragSurface
}));
draggable.subscribe(dragSurface);
dragSurface.pipe(this._eventOutput); // so we can emit a custom removed event to this widget
}
}
module.exports = DragTest;
});
require(['main']);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://requirejs.org/docs/release/2.1.16/minified/require.js"></script>
<script src="http://code.famo.us/lib/requestAnimationFrame.js"></script>
<script src="http://code.famo.us/lib/classList.js"></script>
<script src="http://code.famo.us/lib/functionPrototypeBind.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.famo.us/famous/0.3.5/famous.css" />
<script src="http://code.famo.us/famous/0.3.5/famous.min.js"></script>

Resources