I'm creating a flask app and try to fetch coordinates from mysql DB, the database has latitude and longitude infomation, I'd like to show all of markers on the page with the lat/lng and tend to using js to add markers, don't know why it doesn't work. Any helps appreciated.
using flask sqlalchemy to get lat/lng info
<script>
$(document).ready(function () {
function initMap() {
var latlng = {lat: -37.8253632, lng: 144.1404107}; // THIS IS CENTER OF THE MAP
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 10,
center: latlng
});
google.maps.event.addListenerOnce(map, 'tilesloaded', addMarkers);
function addMarkers() {
{% for CarD in page_data %}
var point = {lat: {{ CarD.lat }}, lng: {{ CarD.lng }} };
var marker = new google.maps.Marker({
position: point,
map: map,
title: '!'
});
{% endfor %}
marker['infowindow'] = new google.maps.InfoWindow({
content: '<div id="content" style="text-align: center"></div>'
}); // info of the point
}
}
});
</script>
Your jinja templates are processed on the server side so putting the python variables in javascript only works if the js is in your template (as in you have the html and js in the same .html file). Additionally, i would discourage you from mixing the code. I would recommend you make an ajax call and receive a json response with your points. In flask you can do something like this
#app.route('/api/coordinates)
def coordinates():
addresses = session.query(Coordinates)#however you query your db
all_coods = [] # initialize a list to store your addresses
for add in addresses:
address_details = {
"lat": add.lat,
"lng": add.lng,
"title": add.title}
all_coods.append(address_details)
return jsonify({'cordinates': all_coods})
then in your javascript you can call this endpoint then process the json object (I like to use fetch for my ajax calls)
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: new google.maps.LatLng(-33.91722, 151.23064),
mapTypeId: 'roadmap'
});
//variable to hold your endpoint
var coodAddresses = 'https://yoursite.com/api/coordinates';
//an array to hold your cordinates
var locations = [];
//Using fetch to process the ajax call
// if you use fetch, besure to include the source below this line in your template
//<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.js"></script>
fetch(coodAddresses)
.then(function(response) {
return response.text();
}).then(function(body) {
var obj = JSON.parse(body);
var myAdd = {};
var addresses = obj.cordinates;
var l = addresses.length;
for (i = 0; i < l; i++) {
myAdd = {
position: {
lat: parseFloat(obj.cordinates[i].lat),
lng: parseFloat(obj.cordinates[i].lng)
},
title: obj.cordinates[i].title,
};
locations.push(myAdd);
}
locations.forEach(function(feature) {
var marker = new google.maps.Marker({
position: feature.position,
title: feature.title,
map: map
});
});
}).catch(function() {
// if the ajax call fails display an error in an info window
var pos = {
lat: lat,
lng: lng
};
infoWindow.setMap(map);
infoWindow.setPosition(pos);
infoWindow.setContent('An error occurred, we are unable to retreive cordinates.');
});
}
I hope you find this useful. If your points are not near each other, you may need to make sure the bounds include all of them
Related
var locations = '<?php print_r(json_encode($locations)) ?>'
console.log(locations);
var mymap = new GMaps({
el: '#mymap',
lat: 31.5204,
lng: 74.3587,
zoom:6 });
mymap.addMarker({
lat: 31.5204,
lng: 74.3587,
click: function(e) { alert('This Is Lahore, Pakistan.'); } });
this is response
[{"id":1,"user_id":2,"latitude":"37.33068424","longitude":"37.33063124","attacked_by":"1","created_at":"2020-02-09 00:00:00","updated_at":"2020-02-16 00:00:00"}]
how can i add multiple pointers using this response lang lat?
You should have multiple lan,lat coordinates to add multiple markers like given below.
[
{"id":1,"user_id":2,"latitude":"37.33068424","longitude":"37.33063124","attacked_by":"1","created_at":"2020-02-09 00:00:00","updated_at":"2020-02-16 00:00:00"},
{"id":1,"user_id":2,"latitude":"38.33068424","longitude":"38.33063124","attacked_by":"1","created_at":"2020-02-09 00:00:00","updated_at":"2020-02-16 00:00:00"},
{"id":1,"user_id":2,"latitude":"39.33068424","longitude":"39.33063124","attacked_by":"1","created_at":"2020-02-09 00:00:00","updated_at":"2020-02-16 00:00:00"}
]
I'm designing a webpage that will be able to retrieve a marker field[geopoint] that is similar for all documents in the collection from firestore and displays all the different documents' fields in an infowindow.
However, on retrieving the marker, I can only see one marker and its fields and not the rest of the other documents' fields.
Screenshots of the collection:
document1 document2 document3
On clicking the marker, only one document is being displayed on the map
Here's the code:
<?php
include_once 'header.php';
?>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-firestore.js"></script>
<div id="map"></div>
<!------ Include the above in your HEAD tag ---------->
<script>
firebase.initializeApp({
apiKey: "xxxxxxxxxxx",
authDomain: "xxxxxxxxxxx",
projectId: "xxxxxxxxxxx"
});
const db = firebase.firestore();
db.settings({timestampsInSnapshots: true});
var map;
var marker;
var infowindow;
var green_icon = 'http://maps.google.com/mapfiles/ms/icons/green-dot.png' ;
var purple_icon = 'http://maps.google.com/mapfiles/ms/icons/purple-dot.png' ;
function initMap() {
var options = {
zoom: 8,
center: {lat: 1.2921, lng: 36.8219}
};
var map = new google.maps.Map(document.getElementById('map'),options);
function addMarker(coords, icon, content, animation){
var marker = new google.maps.Marker({
position: coords,
map: map,
icon: icon,
animation: animation
});
var infoWindow = new google.maps.InfoWindow({
content: content
});
marker.addListener('click', function() {
infoWindow.open(map,marker);
});
}
db.collection('Nairobi').get().then((snapshot) => {
// var data = snapshot.data();
snapshot.docs.forEach(function(child){
var name_loc = child.id;
var loc = child.data().marker;
var forward = child.data().ForwardPower;
var reflected = child.data().ReflectedPower;
var ups = child.data().UPSError;
var upsDesc = child.data().UPSDesc;
var trans = child.data().TransmitterError;
var transDesc = child.data().TransDesc;
addMarker(
{lat: loc.latitude, lng: loc.longitude },
'http://maps.google.com/mapfiles/ms/icons/green-dot.png', '' +
`<h1> ${name_loc}</h1>` + "<br/>"
+ `<h2> Forward Power: ${forward} </h2>`
+ "<br/>" + `<h2> Reflected Power: ${reflected} </h2>`
+ "<br/>" + `<h2> UPS Error: ${ups} </h2>`
+ "<br/>" + `<h2> TransmitterError: ${trans} </h2>`
);
console.log(child.id, child.data());
});
})
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?language=en&key=[API KEY]&callback=initMap">
</script>
On the web console, there is no error and I get back arrays of the documents as shown below: console
You have exactly the same values of markers for the three Firestore documents! So the markers are stacked on your map and you only see one.
Just change the values and you will see the three different markers since your code works.
Also note that you could do:
snapshot.forEach(function(child){...})
instead of
snapshot.docs.forEach(function(child){...})
See https://firebase.google.com/docs/reference/js/firebase.firestore.QuerySnapshot?authuser=0#for-each
As an addition to Renaud's answer, this is indeed intended behaviour, by default Google Maps API displays only top marker.
To achieve desirable behaviour you can use OverlappingMarkerSpiderfier library, for example.
I am trying to pass php $var to Javascript in google map script. I have address table in DB. And with controller I fetch it to view and now try to pass it in Javascript and iterate it.
But having some trouble I think my code a bit corrupted. By the way I dont have lat and lng, just addresses.
function initMap(){
var options = {
zoom:8,
center:
#foreach($address as $addr){
{!! $addr->address !!}
}
#endforeach
}
var map = new google.maps.Map(document.getElementById("map"), options);
var marker = new google.maps.Marker({
position:
#foreach($address as $addr){
{!! $addr->address !!}
}
#endforeach
map:map
});
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
marker.addListener('click', function () {
infoWindow.open(map, marker);
})
}
And Map API calling
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=MY-KEY&callback=initMap"></script>
controller
public function index()
{
$address = DB::table("allestates")
->get();
return view("home", compact('address'));
}
Address column in DB:
I see a few things that could be causing the issue
Try this:
function initMap(){
var options = {
zoom:8,
center:
'{!! $address[0]->address !!}'
}
var map = new google.maps.Map(document.getElementById("map"), options);
var marker = new google.maps.Marker({
position:
#foreach($address as $addr)
'{!! $addr->address !!}'
#endforeach
map:map
});
var infoWindow = new google.maps.InfoWindow({
content:'content here'
});
marker.addListener('click', function () {
infoWindow.open(map, marker);
})
}
So first of all the #foreach (...) does not use { or }
Second you want to output any information that is not only numeric inside of quotes
Hope this helps
I am using the google maps API to show the last position a form was submitted to my site. So I am pulling the lon and lat values from a php file as variables but I need the script to refresh every 5 seconds so that the maps marker updates without page reload.
Here is the google api script:
<script>
function initialize() {
var myLatlng = new google.maps.LatLng<?php
require($DOCUMENT_ROOT . "php_includes/mobile_loc.php");
?>;
var mapOptions = {
zoom: 15,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Last Scan'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
And here is the php file:
<?php
include_once("php_includes/db_conx.php");
$sql = "SELECT * FROM patdub ORDER BY STR_TO_DATE(Timestamp, '%d/%m/%Y %H:%i:%s') DESC LIMIT 1";
$query = mysqli_query($db_conx, $sql);
$row = mysqli_fetch_array($query);
$lon = $row['Lon'];
$lat = $row['Lat'];
echo "($lat, $lon)";
?>
Any ideas? I've tried different AJAX methods but just can't seem to figure it out!
Edit: The line of code below is basically the bit I need to refresh every 5 seconds but without any div tags or anything because that interferes with the google api script..
<?php require($DOCUMENT_ROOT . "php_includes/mobile_loc.php"); ?>;
You want to call load the file your PHP script is in, assuming that it is in it's own file, you would do that like so and you can then update your DOM using the return from the AJAX call.
You would wrap the AJAX call in a javascript loop such as setInterval() like this:
setInterval(function() {
$.ajax({
url: "php_script.php"
}).done(function(return) {
console.log(return);
});
, 5000);
To call it every 5 seconds.
To incorportate it with your Google function (I have no knowledge of google maps so this may not be 100% accurate):
<script>
function initialize(myLatlng) {
myLatlng = myLatlng || new google.maps.LatLng<?php require($DOCUMENT_ROOT . "php_includes/mobile_loc.php");?>;
var mapOptions = {
zoom: 15,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Last Scan'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
setInterval(function() {
$.ajax(function() {
url: 'php_script.php'
}.done(function(response) {
var latlong = response;
initialize(latLong)
});
}, 5000)
</script>
I am looking for a way to add markers on to a map which I have created in a web page... Here is the code for the page...
<link href='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.css' rel='stylesheet' />
<script src='//api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.js'></script>
<style>
#map {
width: 100%;
height: 600px;
}
</style>
<div id='map' />
<script type='text/javascript'>
var map = L.mapbox.map('map', '[mapname]')
</script>
This renders the map from mapbox - but I cannot figure out how to write a web service to provide the markers. This data is stored in a table in a SQL database.
I understand that I can load a GeoJSON file with the data in - but I am unsure on how to create this file - and how it differs from regular JSON - any help would be grateful!
Thanks
I don't know GeoJSON, but this is how you handle it using the Google Maps v3 API:
For one marker:
lng = (4.502384184313996, 4.461185453845246);
lat = (51.011527400014664, 51.02974935275779);
cur_loc = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({
position: cur_loc, //To be defined with LatLng variable type
draggable: false,
animation: google.maps.Animation.DROP,
icon: image
});
// To add the marker to the map, call setMap();
marker.setMap(map);
For multiple markers retrieved from MySQL (Ajax):
google.maps.event.addListener(map, 'idle', function () {
var bounds = map.getBounds();
var ne_lat = bounds.getNorthEast().lat();
var ne_lng = bounds.getNorthEast().lng();
var sw_lat = bounds.getSouthWest().lat();
var sw_lng = bounds.getSouthWest().lng();
// Call you server with ajax passing it the bounds
$.ajax({
type: "GET",
url: "http://www.zwoop.be/develop/home/bars/bars_get_markers.php",
data: {
'ne_lat': ne_lat,
'ne_lng': ne_lng,
'sw_lat': sw_lat,
'sw_lng': sw_lng
},
datatype: "json",
success: function(data){
if(data){
// In the ajax callback delete the current markers and add new markers
function clearOverlays() {
for (var i = 0; i < array_markers.length; i++ ){
array_markers[i].setMap(null);
}
array_markers = [];
};
clearOverlays();
//parse the returned json obect
//Create a marker for each of the returned objects
var obj = $.parseJSON(data);
$.each(obj, function(index,el) {
var bar_position = new google.maps.LatLng(el.lat, el.lng);
image_bar = "http://www.sherv.net/cm/emoticons/drink/whiskey-smiley-emoticon.gif";
var marker = new google.maps.Marker({
position: bar_position,
map: map,
icon: image_bar
});
//Add info window. With HTML, the text format can be edited.
google.maps.event.addListener(marker, 'click', function() {
if (infowindow){
infowindow.close();
};
content = "<div id='infowindow_container'><h3><a class='profile_name_bar' href='#' id='" + el.profile_id + "'>"+el.profile_name+"</a></h3></div>";
infowindow = new google.maps.InfoWindow({
content: content
});
infowindow.open(map,marker);
});
array_markers.push(marker);
});
//Place the markers on the map
function setAllMap(map) {
for (var i = 0; i < array_markers.length; i++) {
array_markers[i].setMap(map);
}
}
setAllMap(map);
//marker clusterer
var zoom = 17;
var size = size ==-1?null:size;
var style = style ==-1?null:style;
var markerCluster = new MarkerClusterer(map, array_markers,{maxZoom:zoom,gridSize:size});
}
},
error: function (xhr, ajaxOptions, error) {
alert(error);
}
})
});
This code looks at the viewport of the map and loads the markers dynamically. When you zoom / pan, the code will query the database: the LatLng coordinates of the map bounds are sent to the server and the marker coordindates that are found in the database are returned from the Ajax call. The marker coordinates are loaded into an array at the client and written on the map.
I used the marker clusterer to avoid crowded markers.
I hope this helps. I don't know the benefits of the plugin that you are using though.
I'm doing something similar, this is where I'm up to.
I use PHP to get the coordinates from the MySQL database and return something like this:
var geoJson = [
{
type: 'Feature',
"geometry": { "type": "Point", "coordinates": [-77.03, 38.90]},
"properties": {}
},
{
type: 'Feature',
"geometry": { "type": "Point", "coordinates": [-64.567, 32.483]},
"properties": {}
}
];
The PHP file looks something like this:
<?php
// Connect
$link = mysqli_connect("[host]","[username]","[password]","[database-name]") or die("Error " . mysqli_error($link));
// Get the coordinates of the places
$query = "SELECT * FROM `places`";
$places = $link->query($query);
var geoJson = [<?php
// Loop through places and plot them on map
// This is just building the JSON string
$i = 1;
while($venue = $venues->fetch_assoc()):
if($i > 1){ echo ","; } ?>
{
type: 'Feature',
"geometry": { "type": "Point", "coordinates": [<?php echo $venue['lon']; ?>, <?php echo $venue['lat']; ?>]},
"properties": {}
}
<?php $i++; ?>
<?php endwhile; ?>
];
map.markerLayer.setGeoJSON(geoJson);
Note - This PHP is inside the Javascript that is making the map.
Like I said its early days for me as well. The code above works, but its just as far as I've got so far. The next thing I'm going to look at is JavaScript templates and using them to pull in the data that way. I have a feeling that will be a better way but I'm not sure. Anyway maybe that's useful to you, let me know if you get any further with it :)