Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add color-coded routes and extremely basic route and station tooltips to map #103

Merged
merged 3 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions app/route_rangers_api/static/map.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@
export function initializeMap(coordinates, stations, iconUrl) {
export function initializeMap(coordinates, stations, iconUrl, routes) {
// Initialize the map at center of city
var map = L.map('map').setView(coordinates, 13);

// Add a tile layer
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
attribution:
'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/attribution">CARTO</a>',
// attribution:
// 'Map data (c) <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, (c) <a href="https://carto.com/attribution">CARTO</a>',
subdomains: 'abcd',
maxZoom: 19,
}).addTo(map);

// Custom icon for smaller markers
var smallIcon = L.icon({
iconUrl: iconUrl, // URL to a smaller icon image
iconSize: [15, 15],
iconSize: [15, 15],
iconAnchor: [6, 6],
});

var markers = L.markerClusterGroup();
var markers = L.markerClusterGroup({
disableClusteringAtZoom: 16
});

for (var i = 0; i < stations.length; i++) {
var station = stations[i];
var marker = L.marker([station[0], station[1]],{icon: smallIcon});
var marker = L.marker([station[0], station[1]], { icon: smallIcon });
marker.bindTooltip(station[2]);
console.log(station[2]);
markers.addLayer(marker);
};

map.addLayer(markers);


// Add routes layer

L.geoJSON(routes, {
style: function (feature) {
return {
color: '#' + feature.properties.color,
weight: 3,
"opacity": .7
};
},
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.route_name);
}
}).addTo(map);

};
6 changes: 4 additions & 2 deletions app/route_rangers_api/templates/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ <h2>Transit Map</h2>
<script type="module">
import { initializeMap } from "{% static 'map.js' %}";
var coordinates = {{ coordinates }};
var stations = {{ stations }};
var stations = {{ stations | safe }};
var iconUrl = "{% static 'images/map_pin.png' %}";
initializeMap(coordinates, stations, iconUrl);
var routes = {{ routes | safe}};
// "safe" parameter needed to deal with escaped quotation marks in GeoJSON
initializeMap(coordinates, stations, iconUrl, routes);
</script>
</div>

Expand Down
24 changes: 20 additions & 4 deletions app/route_rangers_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.template import loader
from django.http import Http404
from django.http import Http404, JsonResponse
from django.urls import reverse
from django.views import generic
from django.utils import timezone
Expand All @@ -11,6 +11,8 @@
from app.route_rangers_api.utils.city_mapping import CITY_CONTEXT
from route_rangers_api.models import TransitRoute, TransitStation

import json


def home(request):
context = {"cities_class": "cs-li-link cs-active", "about_class": "cs-li-link"}
Expand All @@ -31,15 +33,28 @@ def dashboard(request, city: str):
# get commute

# get paths
routes = TransitRoute.objects.filter(city="CHI").values(
"geo_representation", "route_name", "color"
routes = TransitRoute.objects.filter(city=CITY_CONTEXT[city]["DB_Name"]) # .values(
# MultiLineString needs to be serialized into a GeoJson object for Leaflet to
# work with it.
# to serialize into GeoJson, need to get out entire Django model object, not just
# the .values("geo_representation", "route_name", "color")
# with .values() you get "AttributeError: 'dict' has no component 'meta'"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great note, do you notice slowness from loading all of these routes? If so maybe this is a candidate for caching since this data will generally not be changing

Copy link
Contributor

@meganhmoore meganhmoore May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this out and it took about a minute to load the chicago page the first time, we may need to look into ways to cache, or auto-load on initialization, or only load some layers at once to reduce how much is being pulled in at a time (but this can be a ticket for later).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This took a minute or two for me to load too. I'm also wondering if splitting this into two functions may be better the pins need to be dynamically loaded and the routes don't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it's taking maybe 30-45 seconds to load and this is probably why. Agree that refactoring to speed it up should be its own ticket

routes_json = serialize(
"geojson",
routes,
geometry_field="geo_representation",
fields=("route_name", "color"),
)

# stations
stations = TransitStation.objects.values().filter(
city=CITY_CONTEXT[city]["DB_Name"]
)
lst_coords = [[point["location"].x, point["location"].y] for point in stations]

lst_coords = [
[point["location"].x, point["location"].y, point["station_name"]]
for point in stations
]

context = {
"City": CITY_CONTEXT[city]["CityName"],
Expand All @@ -53,6 +68,7 @@ def dashboard(request, city: str):
"feedback_class": "cs-li-link",
"coordinates": CITY_CONTEXT[city]["Coordinates"],
"stations": lst_coords,
"routes": routes_json,
}
return render(request, "dashboard.html", context)

Expand Down
Loading