feat: show radius and center map

This commit is contained in:
moanos [he/him] 2025-01-01 20:14:07 +01:00
parent 3881a4f3b4
commit 8b4488484d
4 changed files with 75 additions and 15 deletions

View File

@ -6,35 +6,81 @@
<script src="{% settings_value "MAP_TILE_SERVER" %}/assets/maplibre-gl/maplibre-gl.js"></script>
<link href="{% settings_value "MAP_TILE_SERVER" %}/assets/maplibre-gl/maplibre-gl.css" rel="stylesheet"/>
<!-- add Turf see https://maplibre.org/maplibre-gl-js/docs/examples/draw-a-radius/ -->
<script src="{% static 'fellchensammlung/js/turf.min.js' %}"></script>
<!-- add container for the map -->
<div id="map" style="width:100%;aspect-ratio:16/9"></div>
<!-- start map -->
<script>
{% if map_center %}
var center = [{{ map_center.longitude }}, {{ map_center.latitude }}];
{% else %}
var center = [10.49, 50.68];
{% endif %}
let map = new maplibregl.Map({
container: 'map',
style: '{% static "fellchensammlung/map/styles/colorful.json" %}',
center: [10.49, 50.68],
center: center,
zoom: 5
}).addControl(new maplibregl.NavigationControl());
{% for adoption_notice in adoption_notices_map %}
{% if adoption_notice.location %}
// create the popup
const popup_{{ forloop.counter }} = new maplibregl.Popup({offset: 25}).setHTML(`{% include "fellchensammlung/partials/partial-adoption-notice-minimal.html" %}`);
// create the popup
const popup_{{ forloop.counter }} = new maplibregl.Popup({offset: 25}).setHTML(`{% include "fellchensammlung/partials/partial-adoption-notice-minimal.html" %}`);
// create DOM element for the marker
const el_{{ forloop.counter }} = document.createElement('div');
el_{{ forloop.counter }}.id = 'marker_{{ forloop.counter }}';
el_{{ forloop.counter }}.classList.add('marker');
// create DOM element for the marker
const el_{{ forloop.counter }} = document.createElement('div');
el_{{ forloop.counter }}.id = 'marker_{{ forloop.counter }}';
el_{{ forloop.counter }}.classList.add('marker');
const location_popup_{{ forloop.counter }} = [{{ adoption_notice.location.longitude | pointdecimal }}, {{ adoption_notice.location.latitude | pointdecimal }}];
// create the marker
new maplibregl.Marker({element: el_{{ forloop.counter }}})
.setLngLat(location_popup_{{ forloop.counter }})
.setPopup(popup_{{ forloop.counter }}) // sets a popup on this marker
.addTo(map);
const location_popup_{{ forloop.counter }} = [{{ adoption_notice.location.longitude | pointdecimal }}, {{ adoption_notice.location.latitude | pointdecimal }}];
// create the marker
new maplibregl.Marker({element: el_{{ forloop.counter }}})
.setLngLat(location_popup_{{ forloop.counter }})
.setPopup(popup_{{ forloop.counter }}) // sets a popup on this marker
.addTo(map);
{% endif %}
{% endfor %}
map.on('load', () => {
const radius = {{ search_radius }}; // kilometer
const options = {
steps: 64,
units: 'kilometers'
};
const circle = turf.circle(center, radius, options);
// Add the circle as a GeoJSON source
map.addSource('location-radius', {
type: 'geojson',
data: circle
});
// Add a fill layer with some transparency
map.addLayer({
id: 'location-radius',
type: 'fill',
source: 'location-radius',
paint: {
'fill-color': '#8CCFFF',
'fill-opacity': 0.5
}
});
// Add a line layer to draw the circle outline
map.addLayer({
id: 'location-radius-outline',
type: 'line',
source: 'location-radius',
paint: {
'line-color': '#0094ff',
'line-width': 3
}
});
});
</script>

View File

@ -1,4 +1,6 @@
import logging
from collections import namedtuple
import requests
import json
from math import radians, sqrt, sin, cos, atan2
@ -6,6 +8,8 @@ from math import radians, sqrt, sin, cos, atan2
from notfellchen import __version__ as nf_version
from notfellchen import settings
Position = namedtuple('Position', ['latitude', 'longitude'])
def calculate_distance_between_coordinates(position1, position2):
"""

View File

@ -1,7 +1,7 @@
import logging
from django.utils.translation import gettext_lazy as _
from .geo import GeoAPI, LocationProxy
from .geo import LocationProxy, Position
from ..forms import AdoptionNoticeSearchForm
from ..models import SearchSubscription, AdoptionNotice, AdoptionNoticeNotification, SexChoicesWithAll, Location
@ -69,6 +69,13 @@ class Search:
except ValueError:
self.place_not_found = True
@property
def position(self):
if self.area_search and not self.place_not_found:
return Position(latitude=self.location.latitude, longitude=self.location.longitude)
else:
return None
def adoption_notice_fits_search(self, adoption_notice: AdoptionNotice):
# Make sure sex is set and sex is not set to all (then it can be disregarded)
if self.sex is not None and self.sex != SexChoicesWithAll.ALL:

View File

@ -195,12 +195,15 @@ def search(request):
subscribed_search = search.get_subscription_or_none(request.user)
else:
subscribed_search = None
context = {"adoption_notices": search.get_adoption_notices(),
"search_form": search.search_form,
"place_not_found": search.place_not_found,
"subscribed_search": subscribed_search,
"searched": searched,
"adoption_notices_map": AdoptionNotice.get_active_ANs()}
"adoption_notices_map": AdoptionNotice.get_active_ANs(),
"map_center": search.position,
"search_radius": search.max_distance,}
return render(request, 'fellchensammlung/search.html', context=context)