2

I am using this code in a Jupyter notebook to open a Google Map.

import gmaps

with open('apikey.txt') as f:
    apikey = f.readline()
    f.close
gmaps.configure(api_key = apikey)

coordinates = (35.5, 140)
map = gmaps.figure(center=coordinates, zoom_level=10, layout={'width': '800px', 'height': '600px'} )
map

I want to find the limits of the map with Python 3.6.

It seems this can be done in JavaScript with the getBounds method which give latitude and longitude for the SW and NE corners of the displayed map. Also, JavaScript seems to allow changes to be tracked with the bounds_changed event.

This is exactly what I want to do but I can't see how in Python.

I have looked through both the gmaps 0.9.0 and googlemaps 4.4.0 plugins with no success.

Anyone done this?

mrigeoy
  • 17
  • 3
  • Have you tried do it with javascript? Using pure gmaps? Is there a problem if I put a awswer in javascript? I did it once using flask and gmaps. Maybe you can hack to make it work with your data. – Danizavtz May 17 '20 at 12:01
  • Thanks for your reply @Danizavtz. Happy to see your javascript code. I'm far more familiar with python so was hoping it could be done. Using javascript was my next move. – mrigeoy May 18 '20 at 06:15

1 Answers1

1

You must use Flask to this solution to work.

pip install flask

Using python-flask create a folder templates in your root project folder. This is a specific behavior from flask, it always lookup html files from templates folder. And create a app.py to start our flask application.

Your project configuration must contain at least that configuration.

.
├── app.py
├── _data
    └── poi.csv
├── _templates
    └── index.html

Just get this lat lon from this question and stuffed with some data to be more clear about how to fill the data.

data/poi.csv

dataa,SclId,Latitude,Longitude,datab
dataa1,HAT-0,44.968046,-94.420307,datab1
dataa2,HAT-1,44.33328,-89.132008,datab2
dataa3,HAT-2,33.755787,-116.359998,datab3

app.py

# python version 3.8.2
import os
from flask import Flask, render_template
from dotenv import load_dotenv
load_dotenv()

class Location:
    def __init__(self,latitude,longitude,produto):
        self.lat = latitude
        self.lon = longitude
        self.nome = produto


def read_data_from_file(caminho):
    lista = list()
    with open(caminho) as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',')
        next(csv_reader)#skip headers
        for row in csv_reader:
            lista.append(Location(row[2], row[3], row[1]))            
        return lista

app = Flask(__name__)
app.config['API_KEY'] = os.getenv("APIKEY")#load google maps api key

def read_dataset(dataset):
    items = list()
    for i in dataset:
        items.append([i.lat, i.lon, i.nome])
    return items

poidata = read_dataset('data/poi.csv')

@app.route('/')
def index():
    context = {
        "key": app.config['API_KEY'],
        "poidata": poidata
    }
    return render_template('./index.html', poidata=poidata, context=context)


if __name__ == '__main__':
    app.run(debug=False)

templates/index.html

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Flask with gmaps</title>
  <style>
    #map-canvas {
      height: 500px;
      width: 100%;
    }
  </style>
</head>

<body>
  <div id="map-canvas">
  </div>
  <script>
    const poiarray = JSON.parse('{{ poidata | tojson | safe}}');

    fillMapItems = (elements, map) => {
      const bounds = new google.maps.LatLngBounds();
      elements.forEach((item, index) => {
        const marker = new google.maps.Marker({ position: new google.maps.LatLng(item[0], item[1]), title: item[2], map: map });
        bounds.extend(marker.position);
      })
      map.fitBounds(bounds);
    }
    showMap = () => {
      const map = new google.maps.Map(document.getElementById('map-canvas'));
      fillMapItems(poiarray, map)
    }
  </script>
  <script async defer src="https://maps.googleapis.com/maps/api/js?key={{ context.key }}&callback=showMap">
  </script>
</body>

</html>

In this code I use python-dotenv, but its use is completely optional, you can use your method to load the env variable with api key loading from file system.

In this line call the LatLngBounds type from googlemaps, we are putting each item from iteration in this "list", after finish iteration just set the map to a distance to fit all points.

const bounds = new google.maps.LatLngBounds();

If you need some clarifications, please let me know.

Danizavtz
  • 3,166
  • 4
  • 24
  • 25
  • I do need clarification. I hit a wall with a `ModuleNotFoundError: No module named 'util'` error. PEP3100 shows the util module was removed from the standard library and I can't see which module to use. – mrigeoy May 19 '20 at 06:21
  • Sorry man, its my local package. I will remove that line from code. This file is just a wrapper for my function to read from file and cast to my class. Can be ignored. – Danizavtz May 19 '20 at 06:23
  • Just updated answer with a full example of my implementations, to be more clear. Sorry. Now you can do some tests with data, only to see if it works. In `app.py` now there is a class `Location` , a `def read_data_from_file`. Added a new folder structure with an example data. – Danizavtz May 19 '20 at 08:56
  • Thanks heaps for your help @Danizavtz. Got this working nicely now. – mrigeoy May 20 '20 at 07:04