Skip to content

Commit

Permalink
Merge pull request #141 from dxw/map-ui
Browse files Browse the repository at this point in the history
Update map UI
  • Loading branch information
jdudley1123 authored Nov 29, 2024
2 parents 8939d9e + 9eae463 commit d372cac
Show file tree
Hide file tree
Showing 117 changed files with 60,323 additions and 59,919 deletions.
25 changes: 17 additions & 8 deletions app/assets/stylesheets/application.tailwind.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,22 @@
border-radius: 0 0 10px 10px;
}

.map {
@apply w-full h-80 mt-2;
}
#map-wrapper {
@apply flex mt-2;

.map {
@apply w-full h-80;
}

.daqi-scale {
@apply flex flex-row;
.daqi-scale {
@apply flex flex-col-reverse;

div {
@apply flex py-1 justify-center items-center;
div {
@apply flex py-1 justify-center items-center;

width: 10%;
width: 2rem;
height: 10%;
}
}
}

Expand Down Expand Up @@ -205,3 +210,7 @@

background-color: #eee;
}

select {
@apply inline-flex flex-row w-full gap-x-1.5 rounded-md bg-white px-3 py-2 text-base font-semibold text-gray-500 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50;
}
50 changes: 41 additions & 9 deletions app/assets/stylesheets/leaflet.scss
Original file line number Diff line number Diff line change
@@ -1,19 +1,45 @@
/* Airtext specific styles */

.leaflet-marker-icon.zone-label {
color: black;
font-size: 12px;
width: auto !important;
height: auto !important;
background-color: white;
padding: 0 3px;
text-align: center;
border-radius: 3px;
opacity: 1;

&.zone-label-level-1 {
font-weight: bold;
}

.wrapper {
display: flex;
transform: translate(-50%, -50%);
color: black;
font-size: 12px;
background-color: white;
text-align: center;
border-radius: 3px;
}

.zone-name {
padding: 0 6px;
}

.daqi-indicator {
padding: 0 6px;
border-right: 1px solid #ccc;
display: flex;
align-items: center;

/*
&::before {
content: "";
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 4px;
background-color: red;
}
*/
}
}

.fullscreen-icon {
Expand All @@ -27,10 +53,16 @@
}
}

.leaflet-control-attribution {
font-size: 50%;
}

.leaflet-bottom.leaflet-left {
bottom: 10px !important;
}

.leaflet-container {
a {
left: 2px !important;

img {
width: 50px; /* Make the Maptiler logo smaller to fit on mobile */
}
Expand Down
18 changes: 17 additions & 1 deletion app/controllers/forecasts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def show
@day = @date ? day_from_date(@date) : day
@pollutant = pollutant

@forecasts = CercForecastService.latest_forecasts_for(@zone).data
@forecasts = CercForecastService.latest_forecasts(@zone).data
@day_forecast = forecast_for_day(@day, @forecasts)
@share_message = @day_forecast.share_message

Expand All @@ -27,6 +27,22 @@ def show
end
end

def pollutant_forecasts
@date = date
@day = @date ? day_from_date(@date) : day
@pollutant = pollutant

latest_forecasts = CercForecastService.latest_forecasts

pollutant_forecasts = latest_forecasts.each_with_object({}) do |zone_forecasts, hash|
zone_name = zone_forecasts.data.first.zone[:name]
forecast = forecast_for_day(@day, zone_forecasts.pollutant_forecasts(@pollutant))
hash[zone_name] = forecast
end

render json: pollutant_forecasts
end

private

def day_from_date(date)
Expand Down
82 changes: 42 additions & 40 deletions app/javascript/controllers/map_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default class MapController extends Controller {
zoomControl: false,
fullscreenControl: true,
fullscreenControlOptions: {
position: "bottomright",
position: "bottomleft",
},
});

Expand Down Expand Up @@ -127,7 +127,7 @@ export default class MapController extends Controller {
addZoomControl() {
L.control
.zoom({
position: "bottomright",
position: "bottomleft",
})
.addTo(this.map);
}
Expand Down Expand Up @@ -165,7 +165,7 @@ export default class MapController extends Controller {

addGeolocationControl() {
new LocateControl({
position: "topright",
position: "topleft",
}).addTo(this.map);
}

Expand Down Expand Up @@ -207,43 +207,24 @@ export default class MapController extends Controller {
}

addZonesLayer() {
const { zoneBoundaryLayers, zoneLabelMarkers } = this.zones();
const zoneBoundaryLayers = this.zoneBoundariesLayers();
zoneBoundaryLayers.forEach((layer) => layer.addTo(this.map));
this.updateZoneBoundaryLayerStyles(zoneBoundaryLayers);

this.map.on("zoomend", () => {
this.updateZoneBoundaryLayerStyles(zoneBoundaryLayers);
});

this.addZoneLabelMarkers(zoneLabelMarkers);
}

zones() {
zoneBoundariesLayers() {
const zoneBoundaryLayers = [];
const zoneLabelMarkers = [];

for (const [, zone] of Object.entries(zones)) {
const layer = L.geoJSON(zone, { pane: "zones" });
zoneBoundaryLayers.push(layer);

const bounds = layer.getBounds();
const center = bounds.getCenter();

const label = L.marker(center, {
icon: L.divIcon({
className:
"zone-label " + `zone-label-level-${zone.properties.level}`,
html: zone.properties.name,
}),
});

zoneLabelMarkers.push({
marker: label,
londonBorough: zone.properties.londonBorough,
});
}

return { zoneBoundaryLayers, zoneLabelMarkers };
return zoneBoundaryLayers;
}

updateZoneBoundaryLayerStyles(zoneBoundaryLayers) {
Expand All @@ -258,27 +239,37 @@ export default class MapController extends Controller {
});
}

addZoneLabelMarkers(zoneLabelMarkers) {
async updateZoneLabels() {
const pollutant_forecasts = await this.getForecastData();

// Remove existing zone labels
this.layers.zoneLabels?.forEach((marker) => this.map.removeLayer(marker));
this.layers.zoneLabels = [];

// Only show the zone labels when the map is zoomed in enough
zoneLabelMarkers.forEach(({ marker, londonBorough }) => {
const startZoom = 9 + (londonBorough ? 2 : 0); // Only show London borough labels at higher zoom
for (const [, zone] of Object.entries(zones)) {
const startZoom = 9 + (zone.properties.londonBorough ? 2 : 0); // Only show London borough labels at higher zoom
const endZoom = 20;

// Add the marker to the map initially if within the zoom range
// Add the marker to the map if within the zoom range
if (this.map.getZoom() >= startZoom && this.map.getZoom() <= endZoom) {
const center = {
lat: zone.properties.center[1],
lng: zone.properties.center[0],
};
const pollutant_value = pollutant_forecasts[zone.properties.name];

const marker = L.marker(center, {
icon: L.divIcon({
className:
"zone-label " + `zone-label-level-${zone.properties.level}`,
html: `<div class="wrapper"><span class="daqi-indicator">${pollutant_value}</span><span class="zone-name">${zone.properties.name}</span></div>`,
}),
});
marker.addTo(this.map);
this.layers.zoneLabels.push(marker);
}

// Attach the zoomend event to control visibility
this.map.on("zoomend", () => {
const currentZoom = this.map.getZoom();
if (currentZoom >= startZoom && currentZoom <= endZoom) {
this.map.addLayer(marker);
} else {
this.map.removeLayer(marker);
}
});
});
}
}

findZones(coordinatesLngLat) {
Expand All @@ -303,10 +294,21 @@ export default class MapController extends Controller {
updateMap() {
this.updateSettings();
this.updatePollutionLayer();
this.updateZoneLabels();
}

updatePollutionLayer() {
this.map.removeLayer(this.layers.pollution);
this.addPollutionLayer();
}

async getForecastData() {
const pollutant = this.pollutantSelectorTarget.value;
const date = this.daySelectorTarget.value;

const response = await fetch(
`/pollutant_forecasts?pollutant=${pollutant}&date=${date}`
);
return response.json();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"type": "Feature",
"properties": {
"name": "Cambridge",
"level": 1
"level": 1,
"center": [0.13, 52.2]
},
"geometry": {
"type": "Polygon",
Expand Down
Loading

0 comments on commit d372cac

Please sign in to comment.