I’m trying to display a map from an MBTiles file using Leaflet, Flask and Sqlite3. I have an MBTiles file of the New Zealand map, and I want to display a location with latitude and longitude values on a web page. I am able to serve the tiles using a Flask route, but when I load the page in my browser, only the controls for the map are displayed, and the map itself is not visible.
Here is what the web page looks like:
Here’s my Flask app code (app.py
):
import sqlite3
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def display_map():
longitude = 175.6138189
latitude = -40.34256356
return render_template('map.html', lat=latitude, lon=longitude)
@app.route('/tiles/<int:z>/<int:x>/<int:y>.png')
def serve_tile(z, x, y):
mbtiles_path = 'path/to/new-zealand.mbtiles'
with sqlite3.connect(mbtiles_path) as conn:
cursor = conn.cursor()
cursor.execute(
'SELECT tile_data FROM tiles WHERE zoom_level=? AND tile_column=? AND tile_row=?',
(z, x, (2 ** z) - 1 - y)
)
tile = cursor.fetchone()
if tile:
return tile[0], 200, {
'Content-Type': 'image/png',
'Cache-Control': 'public, max-age=3600'
}
return 'Tile not found', 404
if __name__ == '__main__':
app.run(debug=True)
And here’s my map.html
file:
<!DOCTYPE html>
<html>
<head>
<title>Location on Map</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
</head>
<body>
<div id="map" style="width: 100%; height: 100vh;"></div>
<script>
var lat = parseFloat("{{ lat|tojson|safe }}");
var lon = parseFloat("{{ lon|tojson|safe }}");
console.log("Latitude: ", lat);
console.log("Longitude: ", lon);
var map = L.map('map').setView([lat, lon], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Map data © OpenStreetMap contributors'
}).addTo(map);
L.marker([lat, lon]).addTo(map).bindPopup("<b>Location</b><br>Latitude: " + lat + "<br>Longitude: " + lon).openPopup();
</script>
</body>
</html>
When I load the page in my browser, I get the following error in the console:
map.html:15 Latitude: NaN
map.html:16 Longitude: NaN
Uncaught Error: Invalid LatLng object: (NaN, NaN)
at new D (LatLng.js:32:9)
at j (LatLng.js:123:11)
at i.setView (Map.js:181:30)
at map.html:18:32.
I suspect that the javascipt code is not receiving the latitude and longitude values from the app.py
. That is probably why it is saying the above error.
How can I resolve this issue and display the map with the correct location using the MBTiles file?
I served the tiles using a Flask route, but encountered issues with displaying the map on the web page. I made changes to the Flask app code and HTML file to try to resolve the issue, such as passing the latitude and longitude values to the template using Flask’s render_template function and using the tojson filter to convert the values to JSON.