I recently started programing in javascript.
I have added a layer control window to my map. It's open by default (This works.). Now I want to add a close button to the layer control window. Is that possible?
This my code:
$ (document).ready(function init(){
// initiate leaflet map
var map = new L.Map('cartodb-map', {
center: [51,9],
zoom: 4,
minZoom:3,
maxZoom: 16,
});
//load basemap
var OSM= new L.tileLayer('http://a{s}.acetate.geoiq.com/tiles/acetate-hillshading/{z}/{x}/{y}.png',
{attribution: '© OpenStreetMap'}).addTo(map);
//load data from CartoDB
var layerUrl= 'http://intermodalmap.cartodb.com/api/v2/viz/0931f4e4-76f8-11e4-0e9d821ea90d/viz.json';
//load satellit map
var Esri_WorldImagery = new L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' });
var baseLayers = { "Standardkarte": OSM,
"Satellitenkarte": Esri_WorldImagery };
//create map
cartodb.createLayer(map, layerUrl,
{https: true,
legends: true,
cartodb_logo:false,
layerIndex: 1
})
.addTo(map)
.on('done', function() {
});
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
var control = new L.Control.Custom(baseLayers, {"Alle Terminals":layerUrl}, {collapsed:false}).addTo(map);
// create a fullscreen button and add it to the map
L.control.fullscreen({
position: 'topleft', // change the position of the button can be topleft, topright, bottomright or bottomleft, defaut topleft
title: 'Open fullscreen', // change the title of the button, default Full Screen
titleCancel: 'Exit fullscreen mode', // change the title of the button when fullscreen is on, default Exit Full Screen
content: null, // change the content of the button, can be HTML, default null
forceSeparateButton: true
}).addTo(map);
// events are fired when entering or exiting fullscreen.
map.on('enterFullscreen', function(){
console.log('entered fullscreen');
});
map.on('exitFullscreen', function(){
console.log('exited fullscreen');
});
//add scale
L.control.scale({metric:"m", position:"bottomright", imperial:false}).addTo(map);
//end of function init
}
)
You can extend L.Control.Layers and add elements to it's container, attach eventhandlers, whatever you want. Something like this:
L.Control.Custom = L.Control.Layers.extend({
onAdd: function () {
this._initLayout();
this._addButton();
this._update();
return this._container;
},
_addButton: function () {
var elements = this._container.getElementsByClassName('leaflet-control-layers-list');
var button = L.DomUtil.create('button', 'my-button-class', elements[0]);
button.innerText = 'Close control';
L.DomEvent.on(button, 'click', function(e){
L.DomEvent.stop(e);
this._collapse();
}, this);
}
});
Example: http://plnkr.co/edit/Je7c0m?p=preview
cartodb.createLayer(map, layerUrl, {
layerIndex: 1
}).addTo(map)
.on('done', function(layer) {
L.control.layers(baseLayers,
{data:layer},
{collapsed:false}
).addTo(map);
document.getElementById('closeBtn').addEventListener('click', function() {
layer.setAttribute('style', 'display: none;').hide();
});
});
// and more shortly if jquery exists
$('#closeBtn').click(function() {
layer.hide();
});
Related
I am making a mashup website that involves a map, and a search textbox in javascript. So as the title says, no matter what is inputted into the search box, only 2 commas appear in the suggestion box and when the suggestion is clicked on, it turn the map gray and unusable. Whats the problem? This is my javascript file, the function where this is located is in the configure function
// Google Map
var map;
// markers for map
var markers = [];
// info window
var info = new google.maps.InfoWindow();
// execute when the DOM is fully loaded
$(function() {
// styles for map
// https://developers.google.com/maps/documentation/javascript/styling
var styles = [
// hide Google's labels
{
featureType: "all",
elementType: "labels",
stylers: [
{visibility: "off"}
]
},
// hide roads
{
featureType: "road",
elementType: "geometry",
stylers: [
{visibility: "off"}
]
}
];
// options for map
// https://developers.google.com/maps/documentation/javascript/reference#MapOptions
var options = {
center: {lat: 35.7640, lng: -78.7786}, // Cary, North Carolina
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP,
maxZoom: 14,
panControl: true,
styles: styles,
zoom: 13,
zoomControl: true
};
// get DOM node in which map will be instantiated
var canvas = $("#map-canvas").get(0);
// instantiate map
map = new google.maps.Map(canvas, options);
// configure UI once Google Map is idle (i.e., loaded)
google.maps.event.addListenerOnce(map, "idle", configure);
});
/**
* Adds marker for place to map.
*/
function addMarker(place)
{
var url = "/search?q=" + place;
$.getJSON(url, function(data){
var location = data.latitude + data.longitude;
mark = new google.maps.marker(location, map);
markers[0] = mark;
});
}
/**
* Configures application.
*/
function configure()
{
// update UI after map has been dragged
google.maps.event.addListener(map, "dragend", function() {
// if info window isn't open
// http://stackoverflow.com/a/12410385
if (!info.getMap || !info.getMap())
{
update();
}
});
// update UI after zoom level changes
google.maps.event.addListener(map, "zoom_changed", function() {
update();
});
// configure typeahead
$("#q").typeahead({
highlight: false,
minLength: 1
},
{
display: function(suggestion) { return null; },
limit: 10,
source: search,
templates: {
suggestion: Handlebars.compile(
"<div>" +
"<p>{{ place_name }}, {{ admin_name1 }}, {{ postal_code }}</p>" +
"</div>"
)
}
});
// re-center map after place is selected from drop-down
$("#q").on("typeahead:selected", function(eventObject, suggestion, name) {
// set map's center
map.setCenter({lat: parseFloat(suggestion.latitude), lng: parseFloat(suggestion.longitude)});
// update UI
update();
});
// hide info window when text box has focus
$("#q").focus(function(eventData) {
info.close();
});
// re-enable ctrl- and right-clicking (and thus Inspect Element) on Google Map
// https://chrome.google.com/webstore/detail/allow-right-click/hompjdfbfmmmgflfjdlnkohcplmboaeo?hl=en
document.addEventListener("contextmenu", function(event) {
event.returnValue = true;
event.stopPropagation && event.stopPropagation();
event.cancelBubble && event.cancelBubble();
}, true);
// update UI
update();
// give focus to text box
$("#q").focus();
}
/**
* Removes markers from map.
*/
function removeMarkers()
{
// TODO
}
/**
* Searches database for typeahead's suggestions.
*/
function search(query, syncResults, asyncResults)
{
// get places matching query (asynchronously)
var parameters = {
q: query
};
$.getJSON(Flask.url_for("search"), parameters)
.done(function(data, textStatus, jqXHR) {
// call typeahead's callback with search results (i.e., places)
asyncResults(data);
})
.fail(function(jqXHR, textStatus, errorThrown) {
// log error to browser's console
console.log(errorThrown.toString());
// call typeahead's callback with no results
asyncResults([]);
});
}
/**
* Shows info window at marker with content.
*/
function showInfo(marker, content)
{
// start div
var div = "<div id='info'>";
if (typeof(content) == "undefined")
{
// http://www.ajaxload.info/
div += "<img alt='loading' src='/static/ajax-loader.gif'/>";
}
else
{
div += content;
}
// end div
div += "</div>";
// set info window's content
info.setContent(div);
// open info window (if not already open)
info.open(map, marker);
}
/**
* Updates UI's markers.
*/
function update()
{
// get map's bounds
var bounds = map.getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
// get places within bounds (asynchronously)
var parameters = {
ne: ne.lat() + "," + ne.lng(),
q: $("#q").val(),
sw: sw.lat() + "," + sw.lng()
};
$.getJSON(Flask.url_for("update"), parameters)
.done(function(data, textStatus, jqXHR) {
// remove old markers from map
removeMarkers();
// add new markers to map
for (var i = 0; i < data.length; i++)
{
addMarker(data[i]);
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
// log error to browser's console
console.log(errorThrown.toString());
});
};
Nvm, figured out that in my application.py, I should have put jsonify(value) instead of jsonify([value]).
i want to display a popup on mouse hover,i want to show names on popup,which will be select from the array list,i placed multiple markers on map at different latlon,now i want to display a popup(which contain name) for particular latlon,this is my code,where i want to show my district name on mouse hover,now i am getting the popup text on mouse hover but i don't know how can i call my array list in popupcontent,any one can suggest what i should do?
var planes = [
["Jodhpur",26.28, 73.02],
["Bikaner",28.0229,73.3119],
["Churu",28.3254,74.4057],
["Ganga Nagar",29.9038,73.8772],
["Hanumangarh",29.1547,74.4995],
["Jaisalmer", 26.9157,70.9083],
["Jalore",25.1257,72.1416],
["Jhunjhunu",28.1289,75.3995],
["Nagaur",27.1854,74.0300],
["Pali",25.7711, 73.3234],
["Sikar",27.6094,75.1399],
["Sirohi",24.7467,72.8043],
["Barmer",25.7532,71.4181],
];
for (var i = 0; i < planes.length; i++) {
marker = new L.marker([planes[i][1],planes[i][2]],{icon: myIcon}).addTo(map).bindPopup('<div id="chart" class="chart"></div>');
marker.on('click', onMarkerClick, this);
/*var currentMarker = planes[i][0];
currentMarker.on('mouseover', currentMarker.openPopup.bind(currentMarker));
*/
marker.on('mouseover', function(e) {
//open popup;
var popup = L.popup()
.setLatLng(e.latlng)
.setContent('Popup')
.openOn(map);
});
}
Filter your array to return the name based on lat and/or lng
marker.on('mouseover', function(e) {
var name = "";
$.each(planes,function(i,v){
if (v.indexOf(e.latlng[0]) > 0) {//test if the lat is in the array
name = v[0];//get the name
}
})
var popup = L.popup()
.setLatLng(e.latlng)
.setContent('District: '+name)
.openOn(map);
})
Note: i am assuming e.latlng is a array of [lat,lng]
You have to change the marker1 name as per your marker name.
var marker1 = L.marker(23.0225, 72.5714).addTo(mymap)
.bindPopup("Demo Content of Popup");
let isClicked = false
marker1.on({
mouseover: function() {
if(!isClicked) {
this.openPopup()
}
},
mouseout: function() {
if(!isClicked) {
this.closePopup()
}
},
click: function() {
isClicked = true
this.openPopup()
}
})
mymap.on ({
click: function() {
isClicked = false
},
popupclose: function () {
isClicked = false
}
})
I have a form that is dynamically inserted into the Google Map. However I cannot click any of the inputs. I believe I need to add a listener somewhere but I'm not sure.
Fiddle
function googlemap() {
// google map coordinates
var posY = 37.765700,
posX = -122.449134,
location = new google.maps.LatLng(posY,posX),
// offset location
posY = posY + 0.055;
offsetlocation = new google.maps.LatLng(posY,posX);
var mapOptions = {
panControl: false,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
draggable: true,
disableDoubleClickZoom: false,
scrollwheel: false,
zoom: 12,
center: offsetlocation,
// ROADMAP; SATELLITE; HYBRID; TERRAIN;
mapTypeId: google.maps.MapTypeId.ROADMAP
};
overlay.prototype = new google.maps.OverlayView();
// create overlay marker
overlay.prototype.onAdd = function() {
blip = document.createElement('div'),
pulse = document.createElement('div');
blip.className = 'blip';
pulse.className = 'pulse';
// createa dialog and grab contents from #mapcontents
boxText = document.createElement("div");
boxText.className = "dialog";
mapContents = $('#mapcontents').html();
boxText.innerHTML = mapContents;
$('#mapcontents').remove();
blip.appendChild(boxText);
// append 'blip' marker
this.getPanes().overlayLayer.appendChild(blip).appendChild(pulse);
}
// update blip positioning when zoomed
overlay.prototype.draw = function(){
var overlayProjection = this.getProjection(),
bounds = new google.maps.LatLngBounds(location, location),
sw = overlayProjection.fromLatLngToDivPixel(bounds.getSouthWest()),
ne = overlayProjection.fromLatLngToDivPixel(bounds.getNorthEast());
blip.style.left = sw.x + 'px';
blip.style.top = ne.y + 'px';
// shift nav into view by resizing header
var w = $('.dialog').width(),
w = (w / 2) + 25,
w = '-' + w + 'px';
h = $('.dialog').height(),
h = (h) + 100,
h = '-' + h + 'px';
$('.dialog').css({
'margin-top' : h,
'margin-left' : w
});
};
var map = new google.maps.Map(document.getElementsByClassName('map')[0], mapOptions);
// explicitly call setMap on this overlay
function overlay(map) {
this.setMap(map);
}
// center map when window resizes
google.maps.event.addDomListener(window, 'resize', function() { map.setCenter(location) });
// center map when zoomed
google.maps.event.addListener(map, 'zoom_changed', function() { map.setCenter(location) });
// I have nfi what I'm doing but I think this click listener is part of the solution.
google.maps.event.addListener('.dialog', 'click', function() {
alert('ok');
});
// process contact form
google.maps.event.addListener(map, 'domready', function() {
$('button').click(function(e) {
(e).preventDefault();
alert('ok');
return false;
var name = $(".contactform input[name='name']"),
email = $(".contactform input[name='email']"),
message = $(".contactform textarea[name='message']"),
error = false;
// clear validation errors
$('#contact input, #contact textarea').removeClass('error');
if(name.val().length < 1)
name.addClass("error");
if(!/^[a-zA-Z0-9._+-]+#[a-zA-Z0-9-]+\.[a-zA-Z]{2,4}(\.[a-zA-Z]{2,3})?(\.[a-zA-Z]{2,3})?$/.test(email.val()))
email.addClass("error");
if(message.val().length < 1)
message.addClass("error");
// if error class exists
if($(".error").length) return false;
$(this).attr('disabled', true).prepend('<i class="load animate-spin"></i>');
$.ajax({
type: "post",
dataType: "json",
url: "lib/sendmail.php",
data: $("#contactform").serialize()
})
.always(function(data) {
$('h5').animate({opacity:0},function(){
$('h5').text("Email Sent!!")
.animate({opacity:1});
});
$('.contactform').animate({opacity:0},function(){
$('.contactform').html("<p class='success'>Thank You for your form submission. We will respond as soon as possible.</p>")
.animate({opacity:1});
})
});
});
return false;
});
// add overlay
overlay = new overlay(map);
}
Any idea why I can't click the inputs?
You just need to block propagation of mousedown map event to make inputs clickable:
google.maps.event.addDomListener(blip, 'mousedown', function (e) {
e.cancelBubble = true;
if(e.stopPropogation) {
e.stopPropagation();
}
});
And you can do the same for dbclick to prevent map zooming: http://jsfiddle.net/gfKWz/1/
The click-events fire fine for all these inputs, the issue here at first is that your code will never execute, because there is no domready-event for a google.maps.Map
Change this:
google.maps.event.addListener(map, 'domready', function () {
into this:
google.maps.event.addListenerOnce(map, 'tilesloaded', function () {
for observation of the events you may use $.on(), e.g.:
$(map.getDiv()).on('click','button',function (e) {/*some code*/});
Demo: http://jsfiddle.net/doktormolle/jcfDu/
You use $('button').click which is triggered before the button is present on the dom. .click() binds the handler to all the current elements on the dom.
Better use $('button').on('click', function(){}); which binds the click event handler to all the current and future instances of button on your page. This is especially handy if you dynamically add content on the page. Through ajax or otherwise.
Read more about jQuery .on() in here http://api.jquery.com/on/
Your event has to be added in the onAdd function.
Currently, the event handler is created before the element. So it doesn't catch the click on this particular element.
http://jsfiddle.net/NeekGerd/duEEt/4/
Or you could create a new function for your overlay's bindings, just for the sake of clean-code :
overlay.prototype.onAdd = function() {
[...]
this.bindings();
}
overlay.prototype.bindings = function(){
$("button").on("click",function(){
alert("Click");
return false;
}
}
For now I have no real solution to your inputs problem.
Maybe by reattaching mousedownevents to them, and force them to focus():
$("input,textarea").on("mousedown",function(){$(this).focus();});
Same thing with your checkboxes.
On another note, since you use jQuery, why not use it all the way?
Like you can do:
$('#mapcontents')
.clone()
.wrap('<div class="dialog" />')
.wrap('<div class="blip />')
.appendTo( *selector* );
In order to quickly build some html and append it to the selected element. Much more readable (thus easier to maintain) than the DOM code you got there. Since you already use jQuery anyway.
I made a mapping application that uses the drawing manager (and implements selectable shapes). The program works as follows: when finishing drawing the polygon after clicking a button a path, is mapped on the polygon.
When the polygon is edited after this process I want the mapping function to be called again. However I can't get this part working:
I tried using following code, but I always get an error because no shape is selected yet when this listener is added. What can I do?
google.maps.event.addListener(selectedShape, 'set_at', function() {
console.log("test");
});
google.maps.event.addListener(selectedShape, 'insert_at', function() {
console.log("test");
});
Important pieces of code:
function showDrawingManager(){
var managerOptions = {
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.MARKER, google.maps.drawing.OverlayType.POLYLINE, google.maps.drawing.OverlayType.POLYGON]
},
markerOptions: {
editable: true,
icon: '/largeTDGreenIcons/blank.png'
},
polygonOptions: {
fillColor: "#1E90FF",
strokeColor: "#1E90FF",
},
polylineOptions: {
strokeColor: "#FF273A"
}
}
var drawingManager = new google.maps.drawing.DrawingManager(managerOptions);
drawingManager.setMap(map);
return drawingManager;
}
function clearSelection() {
if (selectedShape) {
console.log("clearSelection");
selectedShape.setEditable(false);
selectedShape = null;
numberOfShapes--;
}
}
function setSelection(shape) {
console.log("setSelection");
clearSelection();
selectedShape = shape;
shape.setEditable(true);
numberOfShapes++;
//getInformation(shape);
}
function initialize(){
//....
var drawingManager = showDrawingManager();
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);
}
});
I solved it by calling .getPath() and putting the listener inside the listener which is called every time a shape is clicked. I think the Google API documentation is not very clear on how to use the set_at so it may be useful for other people too.
// 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() {
google.maps.event.addListener(newShape.getPath(), 'set_at', function() {
console.log("test");
});
google.maps.event.addListener(newShape.getPath(), 'insert_at', function() {
console.log("test");
});
setSelection(newShape);
});
google.maps.event.addListener(yourPolygon.getPath(), 'insert_at', function(index, obj) {
//polygon object: yourPolygon
});
google.maps.event.addListener(yourPolygon.getPath(), 'set_at', function(index, obj) {
//polygon object: yourPolygon
});
The above code is working for me. Where set_at is fired when we modify a polygon area from a highlighted dot (edges) and insert_at is fired when we drag point that is between highlighted edges.
I used them in the polygoncomplete event and after loading a polygon from the database. It is working fine for them.
To avoid the problems mentioned with set_at and dragging, I added the following, which disables event broadcasting for set_at when the drawing is being dragged. I created a class that extends the polygon class, and added this method:
ExtDrawingPolygon.prototype.enableCoordinatesChangedEvent = function(){
var me = this,
superClass = me.superClass,
isBeingDragged = false,
triggerCoordinatesChanged = function(){
//broadcast normalized event
google.maps.event.trigger(superClass, 'coordinates_changed');
};
// If the overlay is being dragged, set_at gets called repeatedly,
// so either we can debounce that or ignore while dragging,
// ignoring is more efficient.
google.maps.event.addListener(superClass, 'dragstart', function(){
isBeingDragged = true;
});
// If the overlay is dragged
google.maps.event.addListener(superClass, 'dragend', function(){
triggerCoordinatesChanged();
isBeingDragged = false;
});
// Or vertices are added to any of the possible paths, or deleted
var paths = superClass.getPaths();
paths.forEach(function(path, i){
google.maps.event.addListener(path, "insert_at", function(){
triggerCoordinatesChanged();
});
google.maps.event.addListener(path, "set_at", function(){
if(!isBeingDragged){
triggerCoordinatesChanged();
}
});
google.maps.event.addListener(path, "remove_at", function(){
triggerCoordinatesChanged();
});
});
};
It added a "coordinates_changed" event to the polygon itself, so other code can just listen for a nice, single, simplified event.
Starting from chrismarx's answer, below is an example of using a new event in TypeScript. I have done a small change of removing superclass and changing references to "me", because there was a problem with undefined reference.
At the top of your file or global configuration file, etc., use:
declare global {
module google.maps {
interface Polygon {
enableCoordinatesChangedEvent();
}
}
}
Then define extension:
google.maps.Polygon.prototype.enableCoordinatesChangedEvent = function () {
var me = this,
isBeingDragged = false,
triggerCoordinatesChanged = function () {
// Broadcast normalized event
google.maps.event.trigger(me, 'coordinates_changed');
};
// If the overlay is being dragged, set_at gets called repeatedly,
// so either we can debounce that or igore while dragging,
// ignoring is more efficient
google.maps.event.addListener(me, 'dragstart', function () {
isBeingDragged = true;
});
// If the overlay is dragged
google.maps.event.addListener(me, 'dragend', function () {
triggerCoordinatesChanged();
isBeingDragged = false;
});
// Or vertices are added to any of the possible paths, or deleted
var paths = me.getPaths();
paths.forEach(function (path, i) {
google.maps.event.addListener(path, "insert_at", function () {
triggerCoordinatesChanged();
});
google.maps.event.addListener(path, "set_at", function () {
if (!isBeingDragged) {
triggerCoordinatesChanged();
}
});
google.maps.event.addListener(path, "remove_at", function () {
triggerCoordinatesChanged();
});
});
};
Finally call extension and add listener:
google.maps.event.addListener(drawingManager, 'overlaycomplete', function (event) {
event.overlay.enableCoordinatesChangedEvent();
google.maps.event.addListener(event.overlay, 'coordinates_changed', function (index, obj) {
// Polygon object: yourPolygon
console.log('coordinates_changed');
});
});
Starting from Thomas' answer, here is an implementation that enables edits to overlays created with DrawingManager, as well as to Features added from GeoJSON.
The main struggle for me was using the google.maps-prefixed overlay types created by DrawingManager alongside similarly named google.maps.Data Feature types created by addFromGeoJson(). Ultimately I ignored the built-in Data object in favor storing everything as a re-created overlay, setting edit event listeners, and then calling setMap() on them individually as they were drawn. The originally drawn overlays and loaded features are discarded.
The process looks something like this:
Initialize the map.
Add an addfeature event listener to detect whenever a feature is added. This will get fired during addGeoJson() for each Feature, getting its corresponding overlay type and geometry and passing them to a utility function addFeature() to create the overlay.
Load any GeoJSON. This will fire the event listener above for every object loaded in.
Initialize the DrawingManager.
Add {overlay}complete event listeners for each type of overlay (polygon, polyline, and marker). When fired, these events first determine if the overlay is valid (e.g. polygons have >= 3 vertices) and then call addFeature(), passing in the overlay type and geometry.
When called, addFeature() re-creates the overlay and sets all applicable event listeners. Finally, the overlay is stored in the array and displayed on the map.
// GeoJSON containing previously stored data (optional)
var imported = {
type: "FeatureCollection",
features: [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-73.985603, 40.748429
],
},
properties: {
activity: "Entry",
}
}, ]
};
// this will fill with map data as you import it from geojson or draw
var features = {
polygons: [],
lines: [],
markers: []
};
// set default drawing styles
var styles = {
polygon: {
fillColor: '#00ff80',
fillOpacity: 0.3,
strokeColor: '#008840',
strokeWeight: 1,
clickable: true,
editable: true,
zIndex: 1
},
polyline: {
strokeColor: '#ffff00',
strokeWeight: 3,
clickable: true,
editable: true,
zIndex: 2
},
marker: {
clickable: true,
draggable: true,
zIndex: 3
}
}
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 40.748429,
lng: -73.985603
},
zoom: 18,
noClear: true,
mapTypeId: 'satellite',
navigationControl: true,
mapTypeControl: false,
streetViewControl: false,
tilt: 0
});
// add this listener BEFORE loading from GeoJSON
map.data.addListener('addfeature', featureAdded);
// load map features from geojson
map.data.addGeoJson(imported);
// initialize drawing tools
var drawingManager = new google.maps.drawing.DrawingManager({
// uncomment below line to set default drawing mode
// drawingMode: 'marker',
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: ['polygon', 'polyline', 'marker']
},
polygonOptions: styles.polygon,
polylineOptions: styles.polyline,
markerOptions: styles.marker
});
drawingManager.setMap(map);
// for each drawing mode, set a listener for end of drawing
drawingManager.addListener('polygoncomplete', function(polygon) {
// delete drawing if doesn't have enough points
if (polygon.getPath().getLength() < 3) {
alert('Polygons must have 3 or more points.');
polygon.getPath().clear();
}
// otherwise create new feature and delete drawing
else {
addFeature('Polygon', polygon.getPath());
polygon.setMap(null);
}
});
drawingManager.addListener('polylinecomplete', function(line) {
// delete drawing if doesn't have enough points
if (line.getPath().getLength() < 2) {
alert('Lines must have 2 or more points.');
line.getPath().clear();
}
// otherwise create new feature and delete drawing
else {
addFeature('Polyline', line.getPath());
line.setMap(null);
}
});
drawingManager.addListener('markercomplete', function(marker) {
// point geometries have only one point by definition,
// so create new feature and delete drawing
addFeature('Point', marker.getPosition());
marker.setMap(null);
updateGeoJSON();
});
}
// this function gets called when GeoJSON gets loaded
function featureAdded(e) {
switch (e.feature.getGeometry().getType()) {
case 'Polygon':
addFeature('Polygon', e.feature.getGeometry().getAt(0).getArray());
break;
case 'LineString':
addFeature('Polyline', e.feature.getGeometry().getArray());
break;
case 'Point':
addFeature('Point', e.feature.getGeometry().get());
}
map.data.remove(e.feature);
}
function addFeature(type, path) {
switch (type) {
case 'Polygon':
var polygon = new google.maps.Polygon(styles.polygon);
polygon.setPath(path);
// listeners for detecting geometry changes
polygon.getPath().addListener('insert_at', someFunction)
polygon.getPath().addListener('set_at', someFunction);
polygon.getPath().addListener('remove_at', someFunction);
polygon.getPath().addListener('dragend', someFunction);
// delete vertex using right click
polygon.addListener('rightclick', function(e) {
if (e.vertex == undefined) return;
if (polygon.getPath().getLength() == 3) {
polygon.setMap(null);
features.polygons = features.polygons.filter(isValid);
} else {
polygon.getPath().removeAt(e.vertex);
outputAsGeoJSON();
}
});
// add it to our list of features
features.polygons.push(polygon);
// and display it on the map
polygon.setMap(map);
break;
case 'Polyline':
var line = new google.maps.Polyline(styles.polyline);
line.setPath(path);
line.getPath().addListener('insert_at', someOtherFunction);
line.getPath().addListener('set_at', someOtherFunction);
line.getPath().addListener('remove_at', someOtherFunction);
line.getPath().addListener('dragend', someOtherFunction);
// allow right-click vertex deletion
line.addListener('rightclick', function(e) {
if (e.vertex == undefined) return;
if (line.getPath().getLength() == 2) {
line.setMap(null);
features.lines = features.lines.filter(isValid);
} else {
line.getPath().removeAt(e.vertex);
outputAsGeoJSON();
}
});
// add it to our list of features
features.lines.push(line);
// and display it on the map
line.setMap(map);
break;
case 'Point':
var marker = new google.maps.Marker(styles.marker);
marker.setPosition(path);
// make a splashy entrance
marker.setAnimation(google.maps.Animation.DROP);
// detect modifications
marker.addListener('drag', function(e) {
// unnecessary bouncing just to throw you off
marker.setAnimation(google.maps.Animation.BOUNCE);
});
marker.addListener('dragend', function(e) {
// make the bouncing stop
marker.setAnimation(null);
})
// allow right-click deletion
marker.addListener('rightclick', function(e) {
marker.setMap(null);
features.markers = features.markers.filter(isValid);
outputAsGeoJSON();
});
// add it to our list of features
features.markers.push(marker);
// and display it on the map
marker.setMap(map);
break;
}
outputAsGeoJSON();
}
function someFunction() {
// do stuff
}
function someOtherFunction() {
// do other stuff
}
// utility function for reuse any time someone right clicks
function isValid(f) {
return f.getMap() != null;
}
function outputAsGeoJSON() {
// we're only using the Data type here because it can export as GeoJSON
var data = new google.maps.Data;
// add all the polygons in our list of features
features.polygons.forEach(function(polygon, i) {
data.add({
geometry: new google.maps.Data.Polygon([polygon.getPath().getArray()]),
properties: {
description: 'I am a polygon'
}
});
});
// and add all the lines
features.lines.forEach(function(line, i) {
data.add({
geometry: new google.maps.Data.LineString(line.getPath().getArray()),
properties: {
description: 'I am a line'
}
});
});
// and finally any markers
features.markers.forEach(function(marker, i) {
data.add({
geometry: new google.maps.Data.Point(marker.getPosition()),
properties: {
description: 'I am a marker'
}
});
});
// GeoJSONify it
data.toGeoJson(function(json) {
document.getElementById('geojson').value = JSON.stringify(json);
});
}
https://jsfiddle.net/pqdu05s9/1/
I'm unable to fire event on pano_change in the Streetview that is embedded in infowindow. I need to get the array getLinks() and getPosition() of the object StreetViewPanorama each time the user navigates in Streetview infowindow. It is declared as below. I really don't understand why (it works for events on marker and infowindow).
//code here
var contentString = '<input type="button" value="Grab this picture" onClick="captureImage()" /> <div id="content" style="width:200px;height:200px;"></div>';
//code here
var infowindow = new google.maps.InfoWindow({
content: contentString
});
//code here//
google.maps.event.addListener(infowindow, 'domready', function() {
if (pano != null) {
pano.unbind("position");
pano.setVisible(false);
}
pano = new google.maps.StreetViewPanorama(document.getElementById("content"), {
navigationControl: true,
navigationControlOptions: {style: google.maps.NavigationControlStyle.ANDROID},
enableCloseButton: false,
addressControl: false,
linksControl: false
});
pano.bindTo("position", marker);
pano.setVisible(true);
});
You need to add google.maps.event.addListener(pano, 'links_changed', XXXX) and google.maps.event.addListener(pano, 'position_changed', XXXXX) in order to get the events.
Initialization
var pano = new google.maps.StreetViewPanorama(<element>, panoramaOptions);
google.maps.event.addListener(pano, 'pano_changed', function() {
// whatever
});
google.maps.event.addListener(pano, 'links_changed', function() {
var links = pano.getLinks();
for (var i in links) {
// whatever
}
});
google.maps.event.addListener(panorama, 'position_changed', function() {
var newPos = pano.getPosition();
});
google.maps.event.addListener(pano, 'pov_changed', function() {
var newPoV = panorama.getPov();
});
Now, every time you have a change in any of those three events (links, pov, position) the relevant function gets called.