I have the following test Google Map: http://dev.driz.co.uk/googlemap/
I'm using the design of Foursquare markers as an example to test out my code and so far I have implemented a simple display of where YOU the user is in the world with a small avatar and when you hover it tells you this in the form of a tooltip.
The next part is using some JSON data: http://dev.driz.co.uk/googlemap/data.json
I want to display those 5 posts on the map using the coordinates that are stored in the data and display them in a similar fashion to the current marker. The user will then hover the marker and be able to see a tooltip with the following information as an example:
Cameron asked:
Is Star Wars 3d still on at the cinema?
2012-05-20 02:31:21
The user should be able to click on the marker to be taken to the post.
I've had a look around the Developer section of Google Maps, but don't seem to getting the right stuff and not sure how best to use it with my tooltip function and map implementation.
Can anyone help? Post some code examples?
Thanks
Follow these steps
Pull the data using an AJAX request and store it in a variable.
You can use jQuery for this. http://api.jquery.com/jQuery.getJSON/
$.getJSON('http://dev.driz.co.uk/googlemap/data.json', function(data){
// loop and add markers
});
Or you can use plain javascript and a JSON parser.
http://www.degraeve.com/reference/simple-ajax-example.php
http://www.json.org/
Loop in data and pick each item and add to map
for (var i = 0; i < data.length; i++) {
var item = data[i];
var markerLatlng = new google.maps.LatLng(item.Post.latitude, item.Post.longitude);
var marker = new google.maps.Marker({
position: markerLatlng
});
marker.item = item; // store information of each item in marker
marker.setMap(map); // where `map` is the instance of Google Map
google.maps.event.addListener(marker, "click", function(mark) {
// retrieve information using `this.item` and create dynamic HTML to show it.
// this.item.Post.datetime, this.item.Post.content etc.
});
}
Related
I have a page to display all markers on a single google map and use map.data.loadGeoJson to achieve this.
The markers link to their respective details page with the following:
map.data.addListener('click', function(event) {
var id = event.feature.getProperty('name');
window.location.href = 'submission-details.php?submission_id='+id;
});
(The property 'name' is a json file property and the ID for each submission).
I would like the details page to also show a map, but only with one marker relevant to that specific details page.
My json type is feature collection, so I think I need a way to target each feature from the collection, rather than just using map.data.loadGeoJson which displays them all.
Not sure where to go from here and struggled to find someone else asking the same question so any help appreciated!
UPDATE
Thanks Duncan.
I added:
map.data.loadGeoJson('../photo_share/upload/file.json', {},function() {
map.data.getFeatureById(53);
map.data.getFeatureById(53).getProperty('name');
console.log(map.data.getFeatureById(53));
console.log(map.data.getFeatureById(53).getProperty('name'));
});
google.maps.event.addDomListener(window, "load", initMap3);
And it does display in console log, but how do I now use this to only display the one marker, because it currently displays all of them still.
The google.maps.Data class has a getFeatureById method. Given you're passing that id into the submission-details.php page, you should be able to use that to get just the single feature.
You still need to use loadGeoJson, and wait until that's loaded before trying to access it; see Google Maps API: getFeatureById for feature collection not working
Update: And then to stop the whole collection displaying, maybe something like this (completely untested)?
map.data.loadGeoJson('../photo_share/upload/file.json', {}, function(features) {
// get the feature you want:
var feature = map.data.getFeatureById(53);
// hide the current set:
map.data.setMap(null);
// wipe out all the current features:
for (var i = 0; i < features.length; i++) {
map.data.remove(features[i]);
}
// add the feature you want back in:
map.data.add(feature);
// display it:
map.data.setMap(map);
});
Recently I asked about referencing the data of an existing GeoJSON Leaflet object. My Leaflet map consists of data coming in a stream to my GeoJSON Leaflet object. User inputs can change a filter for the GeoJSON data, so to make the filter apply to both the existing and new data I am keeping track of my data in an array called myFeatures. Whenever the filters change or an item in myFeatures changes, I do the following:
myGeoJson.clearLayers();
myGeoJson.addData(myFeatures);
This is working to make my map update according to the newly updated feature data or the changes in the filter.
I am applying pop-ups to the GeoJSON object when I initialize my GeoJSON object:
var myGeoJson = L.geoJson(myFeatures, {
style: function(feature) {
...
},
pointToLayer: function(feature, latlng) {
return L.circleMarker(latlng, geojsonMarkerOptions);
},
filter: function(feature, layer) {
...
},
onEachFeature: function(feature, layer) {
if (feature.properties && feature.properties.popupContent) {
layer.bindPopup(feature.properties.popupContent);
}
}
});
When I click on an individual feature, the pop-up appears. However, the pop-up dismisses pretty quickly, thanks to clearLayers and addData being called. :(
Is there some kind of way to stop the pop-up dismissing in this situation?
Or - better question - is there a way to modifying existing data in a GeoJSON object or remove some (not all) data from a GeoJSON object?
To provide some context, my GeoJSON shows circle markers for each feature. The circle markers are colored based on a property of the feature. The property can actually change over time, so the marker's styling needs to be updated. A marker also times out after a while and needs to be removed from the map, but the other markers need to stay on the map.
There are for sure better ways to do that, but if you don't want to modify your code architecture too much, you could just create your popups in a specific layer, which you won't clear when you add your new data.
To give you an idea (markers play below the role of myGeoJson in your example):
var popup_id = {};
var popup_layer = new L.layerGroup();
var markers = new L.layerGroup();
$.each(testData, function(index, p) {
var marker = L.marker(L.latLng(p.lat, p.lon));
markers.addLayer(marker);
popup = new L.popup({offset: new L.Point(0, -30)});
popup.setLatLng(L.latLng(p.lat, p.lon));
popup.setContent(p.text);
popup_id[p.id] = popup;
marker.on('click', function() {
popup_id[p.id].openPopup();
popup_layer.addLayer(popup_id[p.id]);
markers.clearLayers();
})
});
popup_layer.addTo(map);
markers.addTo(map);
You also keep track of all your popups in a dictionary popup_id.
Since you haven't provided us with a JSfiddle it is a bit difficult to find the perfect answer for your case, but I hope that the popup layer (also here in my fiddle) gives you a good direction.
I have looked over the bing maps documentation trying to find an answer to my question. I would prefer to do everything using the bing maps api and not have to add a third party library if possible.
Question: How can I animate a pushpin to make a smooth transition from one set of gps coordinate(longitude/latitude) to another in order to simulate smooth movement of a Pushpin on Bing maps?
Question: can deleting an entire object out of the map.entities array waste enough resources to cause performance issues? If so how can I change the pushpin latitude and longitude properties without deleting the entire object?
Sample code of trying to change the pushpins properties without deleting the object out of the array. This code does not work… I am unsure why it is not working?
map.entities.get(theIndexOfThePushPin)._location.latitude = newLat;
map.entities.get(theIndexOfThePushPin)._location.longitude = newLon;
I create a pushpin like so - This works fine
map.entities.push(new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
text: text,
visible: true,
textOffset: new Microsoft.Maps.Point(0, 5)
}));
Pseudo code for my recursive angular $http call
function BusMoveGPSRefresh() {
$http.get(resourceURL)
.then(function (data) {
if ('if pushpins have not been created') {
//create pushpins...
}
} else {
//delete pushpins out of the array and then recreate them
//with updated lon/lat. Or just update existing objects lon/lat properties if possible?
}
}
BusMoveGPSRefresh();//after everything is done then go get more info and start again. recursion...
}, function (reason) {// if fail than do
console.log(reason);
console.log("This Is not Working!!! Dang!!");
});
}
Any insight into the problem would be greatly appreciated! Thanks!
I could not find a simple answer for adding animation. I did find a site that gave a step by step tutorial on a more in-depth answer on how to animate pushpins.
Answer: 1 -- tutorial on how to animate bing map pushpins
https://blogs.bing.com/maps/2014/08/07/bring-your-maps-to-life-creating-animations-with-bing-maps-javascript/
Answer: 2 -- this is how to update the pushpin location without deleting the pushpin object out of the entities array.
Instead of deleting the entire pushpin object find the pushpin index and then use the property "setLocation()" and then add a new location.
//check to make sure that the lat and lon have
//changed if it is still the same location do nothing. else update
if (map.entities.get(indexOfPushpin).getLocation().latitude != lat
|| map.entities.get(indexOfPushpin).getLocation().longitude != lon) {
map.entities.get(indexOfPushpin).setLocation(new Microsoft.Maps.Location(lat, lon));
}
I am using a simple Mapbox layer control calling MB data layers (below).
I need to add a few more marker layers to this, but not sure how to get a mapbox ID. How can I accomplish this?
L.mapbox.accessToken = 'pk.eyJ1IjoibWFwc3RlciIsImEiOiI3RmFfME5ZIn0.73sdzUFNqSsGQzjlsnimaA';
var map = L.map('map').setView([38.8922,-77.0348], 14);
var layers = document.getElementById('menu-ui');
addLayer(L.mapbox.tileLayer('examples.map-i87786ca'), 'Base Map', 1);
addLayer(L.mapbox.tileLayer('examples.bike-lanes'), 'Bike Lanes', 2);
addLayer(L.mapbox.tileLayer('examples.bike-locations'), 'Bike Stations', 3);
function addLayer(layer, name, zIndex) {
layer
.setZIndex(zIndex)
.addTo(map);
code is from Mapbox toggling layers template
At the moment you're using their example ID and maps. You're not supposed to do that. If you would have read at the bottom of the page you posted it says:
Use this example by copying its source into your own HTML page and replacing the Map ID with one of your own from your projects.
Where "your projects" is linked to https://www.mapbox.com/projects/. When you're not logged in you get a nice dialog which asks you to login or register. Once you've done that you'll get your very own ID and you are able to create projects. When creating a project you'll get a Map ID per project. It's all pretty selfexplanatory.
EDIT: If you want to insert a separate layer with features, you've got to create a project with only a markerlayer. Save it and copy the id. You can include that in another map by using L.mapbox.featureLayer:
var mapId = 'examples.map-zr0njcqy'; // use your feature mapid
var features = L.mapbox.featureLayer(mapId); // declare featureLayer
features.on('ready', function () { // Wait untill features are loaded
addLayer(features); // add it the same your tilelayers
}
You can also use this to load external geojson files by just using an URL instead of a mapid.
See the example: https://www.mapbox.com/mapbox.js/example/v1.0.0/features-from-another-map/
And the reference: https://www.mapbox.com/mapbox.js/api/v2.1.5/l-mapbox-featurelayer/
Ok, here is my situation. I am using the leaflet map module with drupal. I have the map integrated on my website with views. I have nodes that contain content that I want to be displayed via a popup window. When I click each individual marker, the popup works exactly as I want. however, I want to be able to click an external link to be able to also open the popup. I have viewed and implemented this code from another question:
var markers = [];
var marker1 = L.marker([51.497, -0.09],{title:"marker_1"}).addTo(map).bindPopup("Marker 1");
markers.push(marker1);
var marker2 = L.marker([51.495, -0.083],{title:"marker_2"}).addTo(map).bindPopup("Marker 2");
markers.push(marker2);
var marker3 = L.marker([51.49, -0.097],{title:"marker_3"}).addTo(map).bindPopup("Marker 3");
markers.push(marker3);
function markerFunction(id){
for (var i in markers){
var markerID = markers[i].options.title;
if (markerID == id){
markers[i].openPopup();
};
}
}
$("a").click(function(){
markerFunction($(this)[0].id);
});
by user abenrob, but that doesn't work with markers generated by drupal.
My question has 2 parts, as I can see it.
1: How do I access the map inside my different block? I have set up the links from my menu block to call my function that contains the aforementioned code, and they call it correctly. However, when my Javascript needs to speak to the map, I get nothing.
Currently I have "var map = document.getElementById('leaflet-map');", but that seems to be pulling the div, not the map contained inside the div.
2: How do I access the list of markers generated by my map in drupal. Currently, as a test, I am just generating a marker manually and using the bindPopup function to bind the div containing the popup on the page, but I can't add it to the map (see part 1). Ideally I would not want to recreate the markers in javascript if they are already created in Drupal, but we don't always live in an ideal world, but it seems that if I get the map to connect, I could at least work with that.
In case anyone else stumbles across this with the same question, I figured out the first question. I accessed the map created by Drupal through the Leaflet module by utilizing the following code:
// This accesses the leaflet map created by drupal and sets the map variables so that they can be used with the functions
var map;
$(document).bind('leaflet.map', function(e, settingsLeaflet, lMap)
{
map = lMap;
});
I am still working on the second question. When I figure it out, I will add another update.
Edit: I was able to access the markers in the second question by using the following code:
var markers = {};
var markersList = [];
// This accesses the leaflet map features and pulls the marker variables so that they can be used with the functions
$(document).bind('leaflet.feature', function(e, lFeature, feature)
{
markers[feature.feature_id] = lFeature;
markersList.push(lFeature);
});
from there it was as easy as looping through the markers list, as such:
// This function takes the variable id, which is passed from the HTML call of this function. It then loops through the marker list and compares the id with the value of the title of each marker. If it finds a match, then it opens the popup bound to that specific marker.
function markerPopups(id)
{
// Loops through the markers list
for (var i = 0; i < markersList.length; i++)
{
// Sets a variable to get the title of the marker, which
var markerID = markersList[i].options.title.replace(/[^a-zA-Z0-9]/g, '_');
// Compares the variable passed through the function to the title of the marker. If there is a match, it opens the popup for that marker.
if(markerID == id)
{
markersList[i].openPopup();
}
}
}
Also, it wasn't needed to access the map once you accessed the pre-made markers, so you can ignore the first part, unless you need to use the map for anything else.