Google Maps JS API v3 - Simple LineString example - google-maps-api-3

I'm a very experienced C++ and Python programmer but new to the Google Maps API and pretty new to JavaScript. I'm trying to get a simple example working to display part of the path of a train, using the LineString GeoJSON object type, constructed inline. I've tried moving my map dictionary inside a GeoJSON object constructor, modifying the style definition and moving it up and down, etc. But the best I can do is an empty map, I think centered where my overlay should be appearing. Trying this using the current Chrome and jsbin.com in Windows, and Firefox in Centos. Many thanks for any help!
<!DOCTYPE html>
<html>
<head>
<title>Simple Map with StringLine</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lng: -73.945259, lat: 41.133659},
zoom: 15
});
map.data.addGeoJson({
"type": "LineString",
"coordinates": [
[-73.945259094199997, 41.133659362800003],
[-73.945625305199997, 41.178726196299998],
[-73.978820800799994, 41.2158432007],
[-73.978256225600006, 41.249233245799999],
[-73.954887390099998, 41.288650512700002],
[-73.986076354999994, 41.322223663300001],
[-73.965789794900004, 41.352313995400003],
[-73.957283020000006, 41.382507324199999],
[-73.968963622999993, 41.410072326700003],
[-73.989562988299994, 41.439929962199997],
[-74.015953064000001, 41.464096069299998],
[-74.006843566900002, 41.499134063699998],
[-73.999168396000002, 41.5377388],
[-73.9613571167, 41.581764221199997],
[-73.956344604500003, 41.627635955800002],
[-73.948852539100002, 41.678043365500002],
[-73.946556091299996, 41.729282379200001],
[-73.9569854736, 41.7779464722],
[-73.9701004028, 41.828430175800001],
[-73.985443115199999, 41.881973266599999],
[-74.006584167499994, 41.924633026099997],
[-73.991699218799994, 41.975730896000002],
[-73.982696533199999, 42.033111572300001],
[-73.962783813499996, 42.085037231400001]
]
});
map.data.setStyle({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 10,
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
async defer></script>
</body>
</html>

Your GeoJson is not valid for the .addGeoJson method, it throws a javascript error: `Uncaught InvalidValueError: not a Feature or FeatureCollection
(from the javascript console. See Troubleshooting in the documentation)
fiddle
If I make your GeoJson a FeatureCollection it works for me:
updated fiddle
code snippet:
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lng: -73.945259,
lat: 41.133659
},
zoom: 15
});
map.data.addGeoJson({
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [102.0, 0.5]
},
"properties": {
"prop0": "value0"
}
}, {
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-73.945259094199997, 41.133659362800003],
[-73.945625305199997, 41.178726196299998],
[-73.978820800799994, 41.2158432007],
[-73.978256225600006, 41.249233245799999],
[-73.954887390099998, 41.288650512700002],
[-73.986076354999994, 41.322223663300001],
[-73.965789794900004, 41.352313995400003],
[-73.957283020000006, 41.382507324199999],
[-73.968963622999993, 41.410072326700003],
[-73.989562988299994, 41.439929962199997],
[-74.015953064000001, 41.464096069299998],
[-74.006843566900002, 41.499134063699998],
[-73.999168396000002, 41.5377388],
[-73.9613571167, 41.581764221199997],
[-73.956344604500003, 41.627635955800002],
[-73.948852539100002, 41.678043365500002],
[-73.946556091299996, 41.729282379200001],
[-73.9569854736, 41.7779464722],
[-73.9701004028, 41.828430175800001],
[-73.985443115199999, 41.881973266599999],
[-74.006584167499994, 41.924633026099997],
[-73.991699218799994, 41.975730896000002],
[-73.982696533199999, 42.033111572300001],
[-73.962783813499996, 42.085037231400001]
]
}
}]
});
map.data.setStyle({
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 10,
});
}
google.maps.event.addDomListener(window, "load", initMap);
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<!-- added 2/8/2023 to prevent:
Loading the Google Maps JavaScript API without a callback is not supported: https://developers.google.com/maps/documentation/javascript/url-params#required_parameters
-->
<script>
function dummy() {}
window.dummy=dummy;
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=dummy"></script>
<div id="map"></div>

Related

Zoom to Marker location on click -OpenLayers

I am displaying markers on the map from geojson file. In the current code, I can add the markers on the map. I want to add fly to or zoom in marker exact location upon click on the marker.how can I achieve that using OpenLayers.
var cityMarker = new ol.layer.Vector({
source: new ol.source.Vector({
format: new ol.format.GeoJSON(),
url: "data/cities.js"
}),
style: new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 0.5],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
scale:0.03,
src: "icons/red-circle.png"
})
})
});
map.addLayer(cityMarker);
bind singleclick event to map
map.on('singleclick', event => {
// get the feature you clicked
const feature = map.forEachFeatureAtPixel(event.pixel, (feature) => {
return feature
})
if(feature instanceof ol.Feature){
// Fit the feature geometry or extent based on the given map
map.getView().fit(feature.getGeometry())
// map.getView().fit(feature.getGeometry().getExtent())
}
})
A separate HTML file for you!
<!DOCTYPE html>
<html>
<head>
<title>GeoJSON</title>
<link
rel="stylesheet"
href="https://openlayers.org/en/v4.6.5/css/ol.css"
type="text/css"
/>
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script>
var image = new ol.style.Circle({
radius: 5,
fill: null,
stroke: new ol.style.Stroke({ color: "red", width: 1 }),
});
var styles = {
Point: new ol.style.Style({
image: image,
}),
};
var styleFunction = function (feature) {
return styles[feature.getGeometry().getType()];
};
var geojsonObject = {
type: "FeatureCollection",
crs: {
type: "name",
properties: {
name: "EPSG:3857",
},
},
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [0, 0],
},
},
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [13369643, 3572500],
},
},
],
};
var vectorSource = new ol.source.Vector({
features: new ol.format.GeoJSON().readFeatures(geojsonObject),
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: styleFunction,
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
vectorLayer,
],
target: "map",
controls: ol.control.defaults({
attributionOptions: {
collapsible: false,
},
}),
view: new ol.View({
center: [0, 0],
zoom: 2,
}),
});
map.on("singleclick", (event) => {
// get the feature you clicked
const feature = map.forEachFeatureAtPixel(event.pixel, (feature) => {
return feature;
});
if (feature instanceof ol.Feature) {
// Fit the feature geometry or extent based on the given map
map.getView().fit(feature.getGeometry());
// map.getView().fit(feature.getGeometry().getExtent())
}
});
</script>
</body>
</html>

center and fit boundaries of geojson multiple polygon data

I am trying to center and fit the boundaries of multiple geojson polygon features on my google.maps.Map.
See this non geojson fiddle recreating the effect i'm after.
Is there an easy Google Map API 3 function to do this for geojson data?
See my code below and fiddle here
var map;
window.initMap = function() {
var mapProp = {
center: new google.maps.LatLng(51.8948201,-0.7333298),
zoom: 17,
mapTypeId: 'satellite'
};
map = new google.maps.Map(document.getElementById("map"), mapProp);
map.data.loadGeoJson('https://api.myjson.com/bins/g0tzw');
map.data.setStyle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
var bounds = new google.maps.LatLngBounds();
map.fitBounds(bounds);
map.setCenter(bounds.getCenter());
}
I need expert pointers on cleanest and best way approach this.
See working demo of my code above in fiddle.
http://jsfiddle.net/joshmoto/fe2vworc/
I've included my geojson inline so you can see the polygons on the map.
Here is a quick example of how you can get your features bounds. This will just get each feature bounds, extend a LatLngBounds object and then fit the map with these bounds.
var map;
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 10,
center: {
lat: 0,
lng: 0
}
});
var permits = {
type: "FeatureCollection",
id: "permits",
features: [{
type: "Feature",
properties: {
name: "Alpha Field"
},
geometry: {
type: "Polygon",
coordinates: [
[
[-0.72863, 51.895995],
[-0.730022, 51.896766],
[-0.730754, 51.896524],
[-0.731234, 51.896401],
[-0.731832, 51.896294],
[-0.732345, 51.896219],
[-0.732945, 51.896102],
[-0.732691, 51.895774],
[-0.732618, 51.895531],
[-0.732543, 51.895359],
[-0.73152, 51.894751],
[-0.731037, 51.894488],
[-0.730708, 51.894324],
[-0.72863, 51.895995]
]
]
}
},
{
type: "Feature",
properties: {
name: "Beta Field"
},
geometry: {
type: "Polygon",
coordinates: [
[
[-0.728004, 51.895658],
[-0.72863, 51.895995],
[-0.730708, 51.894324],
[-0.731217, 51.893784],
[-0.730992, 51.893709],
[-0.730793, 51.893567],
[-0.730734, 51.893435],
[-0.730761, 51.89333],
[-0.729696, 51.893244],
[-0.729391, 51.89314],
[-0.729249, 51.893586],
[-0.728991, 51.894152],
[-0.728525, 51.894983],
[-0.728004, 51.895658]
]
]
}
}
]
};
google.maps.event.addListenerOnce(map, 'idle', function() {
// Load GeoJSON.
map.data.addGeoJson(permits);
// Create empty bounds object
var bounds = new google.maps.LatLngBounds();
// Loop through features
map.data.forEach(function(feature) {
var geo = feature.getGeometry();
geo.forEachLatLng(function(LatLng) {
bounds.extend(LatLng);
});
});
map.fitBounds(bounds);
});
}
initialize();
#map-canvas {
height: 150px;
}
<div id="map-canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
Props to #MrUpsidown for providing the working method to fitBounds.
I'm posting this answer to show my final solution based on #MrUpsidown answer using GeoJson data via loadGeoJson()
Here is my readable GeoJson here http://myjson.com/g0tzw
// initiate map
window.initMap = function() {
// permits json
var permits = 'https://api.myjson.com/bins/g0tzw';
// map properties
var mapProp = {
zoom: 17,
mapTypeId: 'satellite'
};
// google map object
var map = new google.maps.Map(document.getElementById("map"), mapProp);
// load GeoJSON.
map.data.loadGeoJson(permits, null, function () {
// create empty bounds object
var bounds = new google.maps.LatLngBounds();
// loop through features
map.data.forEach(function(feature) {
var geo = feature.getGeometry();
geo.forEachLatLng(function(LatLng) {
bounds.extend(LatLng);
});
});
// fit data to bounds
map.fitBounds(bounds);
});
// map data styles
map.data.setStyle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
}
I'm calling initMap via...
<script async defer src="https://maps.googleapis.com/maps/api/js?key=<?=$gmap_api?>&callback=initMap"></script>
See working demo here.
http://jsfiddle.net/joshmoto/eg3vj17m/

Google Maps Data Layer features not rendering after 1st feature deletion

I am trying to allow a user to draw a shape in Google Maps using the map.data features layer. As soon as the user finishes drawing, I want to process the coordinates of the shapes they just drew and then immediately remove it from the map. The first shape deletes fine, but after the first they still process and appear to empty out of the object (tested by using the map.data.toGeoJson to log it to the console where it shows the map.data object but with no features present) but they are still visible on the map.
To see what is happening, in the fiddle draw a polygon and on completion (double click) it disappears because it is deleted after processing (which is what should happen). However, when a second or more polygons are drawn they stay visible on the map.
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8
});
map.data.setControls(['Point', 'LineString', 'Polygon']);
map.data.addListener('addfeature', function(event) {
event.feature.getGeometry().forEachLatLng(function(latLng) {
//do stuff with the feature
});
map.data.remove(event.feature);
});
}
Fiddle: https://jsfiddle.net/km76tvhp/13/
This is strange behavior and it could possibly be a bug. As a workaround, you could use the Drawing Library. Here is an example below which uses the google.maps.drawing.DrawingManager. It's very similar to drawing using the google.maps.Data class.
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8
});
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControlOptions: {
drawingModes: ['marker', 'polygon', 'polyline']
},
polygonOptions: {
editable: true,
draggable: true,
strokeColor: 'red'
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'polygoncomplete', function(polygon) {
polygon.getPath().getArray().forEach(function(latLng){
// do stuff with the feature
});
polygon.setMap(null);
});
}
#map {
height: 100%;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap&libraries=drawing" async defer></script>

Googlemap shows grey box on all browsers

I have a simple test site to show google map here:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?libraries=places,geometry"></script>
<script src="js/GoogleMap/GoogleMap_thread_view.js"></script>
<link href="js/GoogleMap/GoogleMap.css" rel="stylesheet" />
<script type="text/javascript">$(document).ready(function () {
$("#googlemap").GoogleMap({addr: "105K Ho Thi Ky Phuong 1 Quan 10 Ho Chi Minh", lat: 43.37049234, lng: 30.3480382});
/*var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('googlemap'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Hello World!'
});*/
});</script>
</head>
<body style="width: 1000px; height: 600px;">
<div id="googlemap" style="width: 1000px; height: 600px; ">abc</div>
</body>
</html>
The page just shows grey div without map.
I searched around on this site but nothing works (resize window event, overflow: visible, width: 100% ... etc ...)
The thing is when I uncomment the Google's sample code, it works. So there must be something wrong with my script, file GoogleMap_thread_view.js
(function ($) {
var map, place, myMarker;
$.widget('4phuong.GoogleMap', {
options: {
addr: 'unknown',
lat: 0,
lng: 0,
zoom: 2
},
_create: function () {
var $widget = this;
$widget.element.children().hide();
$widget._$container = $('<div class="googlemap-container"><div class="map-canvas"></div></div>');
$widget.element.append($widget._$container);
var mapOptions = {
center: new google.maps.LatLng($widget.options.lat, $widget.options.lng),
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL,
position: google.maps.ControlPosition.LEFT_BOTTOM
},
mapTypeControl: false,
streetViewControl: false
};
map = new google.maps.Map(document.getElementsByClassName('map-canvas')[0], mapOptions);
myMarker = new google.maps.Marker({
map: map,
title: $widget.options.addr,
position: new google.maps.LatLng($widget.options.lat, $widget.options.lng)
});
},
destroy: function () {
this._$container.remove();
$.Widget.prototype.destroy.apply(this, arguments);
this.element.show();
},
control: function () {
return this._$control;
}
});
}(jQuery));
Could someone please tell me where I am wrong?
I know the reason. It's because I didn't give value to the field "zoom" when creating map. It should look like below
var mapOptions = {
center: new google.maps.LatLng($widget.options.lat, $widget.options.lng),
zoom: $widget.options.zoom,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL,
position: google.maps.ControlPosition.LEFT_BOTTOM
},
mapTypeControl: false,
streetViewControl: false
};
It's really stupid as Google should make default value for it.

How can I clear a rectangle with Google Maps API V3

I am trying to get the following behaviour. When I click the map I want a rectangle to start appearing. As a move the mouse (not drag) I want the rectangle to adjust itself to fit the first click and the mouse position.
When I click the mouse the second time, I want to capture the corner coordinates (for a spatial search query) and then have the rectangle stop resizing.
On the third mouse click I want the rectangle to disappear.
At the moment the rectangle appears and resizes but it never stops following the mouse.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
div#map { width: 750px; height: 500px; }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"/></script>
<script type="text/javascript">
var start = new google.maps.LatLng();
var clicked=0;
window.onload = function()
{
var settings = {
mapTypeId: google.maps.MapTypeId.TERRAIN, // map type
zoom: 8, // map type
center: new google.maps.LatLng(-33.890542, 151.274856) // coordinates
};
var map = new google.maps.Map(document.getElementById("map"), settings);
rectangle = new google.maps.Rectangle();
google.maps.event.addListener(map, 'click', function(event) {
loc = event.latLng;
if(clicked==0){
$("#start").html(loc.toString());
start=loc;
// start the rectangle
var rectOptions = {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
map: map
};
rectangle.setOptions(rectOptions);
clicked=1;
}
else if(clicked==1){
$("#end").html(loc.toString());
clicked=2;
alert("clicked "+clicked);
}
else if(clicked==2){
$("#start").html("");
$("#dragged").html("");
$("#end").html("");
clicked=0;
}
});
google.maps.event.addListener(map, 'mousemove', function(event) {
if(clicked==1){
loc = event.latLng;
$("#dragged").html(loc.toString());
$("#dragged").html(loc.toString());
var bounds = new google.maps.LatLngBounds();
bounds.extend(start);
bounds.extend(loc);
rectangle.setBounds(bounds);
}
else if(clicked==2){
alert("mouseover: "+clicked);
rectangle.setMap(null);
}
});
};
</script>
</head>
<body>
<div id="map"></div>
</body>
I've just ran into the same problem and I just noticed how old this post is. Everyone that has this problem, you need to check out https://developers.google.com/maps/documentation/javascript/reference#DrawingManager
use that instead of google.maps.Rectangle(); Check This Out:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=drawing"></script>
<script type="text/javascript">
function initialize() {
// render map
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: new google.maps.LatLng( 36.175, -115.1363889 ),
mapTypeControl: false,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.SMALL
},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
// get the DrawingManager - Remember to include &libraries=drawing in the API call
var draw = new google.maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT,
drawingModes: [
google.maps.drawing.OverlayType.CIRCLE,
google.maps.drawing.OverlayType.RECTANGLE,
google.maps.drawing.OverlayType.POLYGON
]
},
rectangleOptions: {
fillColor: '#990000',
fillOpacity: .4,
strokeWeight: 3,
strokeColor: '#999',
clickable: true,
editable: true,
zIndex: 1
}
});
// set the cursor to the rectangle
draw.setDrawingMode(google.maps.drawing.OverlayType.RECTANGLE);
// adds a listener for completed overlays, most work done in here
google.maps.event.addListener(draw, 'overlaycomplete', function(event) {
draw.setDrawingMode(null); // put the cursor back to the hand
if (event.type == google.maps.drawing.OverlayType.CIRCLE) {
//do something
}
if (event.type == google.maps.drawing.OverlayType.POLYGON) {
// do something
}
if (event.type == google.maps.drawing.OverlayType.RECTANGLE) {
// on click, unset the overlay, and switch the cursor back to rectangle
google.maps.event.addListener(event.overlay, 'click', function() {
this.setMap(null);
draw.setDrawingMode(google.maps.drawing.OverlayType.RECTANGLE);
});
}
});
// end of initialize
draw.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);

Resources