Skip to content

Commit

Permalink
WIP web components
Browse files Browse the repository at this point in the history
  • Loading branch information
sephii committed Dec 19, 2020
1 parent cd68cda commit bd98f5f
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 43 deletions.
98 changes: 98 additions & 0 deletions assets/elm/src/Leaflet.elm
@@ -0,0 +1,98 @@
module Leaflet exposing (LeafletMap)

import Browser
import Html exposing (Html, node)
import Html.Attributes exposing (attribute)


type LeafletMap
= LeafletMap
{ id : String
, routes : List Route
, tileUrl : String
, markers : List Marker
}



-- TODO make it opaque


type alias Route =
String



-- TODO make it opaque


type alias Marker =
{ latitude : String
, longitude : String
, body : Html Never
}


type alias Flags =
{ routes : List Route
, tileUrl : String
}


view : LeafletMap -> Html Never
view (LeafletMap leafletMap) =
let
markers =
List.map viewMarker leafletMap.markers

routes =
List.map viewRoute leafletMap.routes
in
node "leaflet-map"
[ attribute "tile-url" leafletMap.tileUrl
, attribute "map-id" leafletMap.id
]
(markers ++ routes)


viewMarker : Marker -> Html Never
viewMarker marker =
node "marker"
[ attribute "lon" marker.longitude
, attribute "lat" marker.latitude
]
[ marker.body ]


viewRoute : Route -> Html Never
viewRoute route =
node "leaflet-route" [ attribute "geojson" route ] []


init : { mapId : String, tileUrl : String } -> LeafletMap
init { mapId, tileUrl } =
LeafletMap { id = mapId, routes = [], tileUrl = tileUrl, markers = [] }


withRoutes : List Route -> LeafletMap -> LeafletMap
withRoutes routes (LeafletMap leafletMap) =
LeafletMap { leafletMap | routes = routes }


withMarkers : List Marker -> LeafletMap -> LeafletMap
withMarkers markers (LeafletMap leafletMap) =
LeafletMap { leafletMap | markers = markers }


main =
let
mainInit : Flags -> ( LeafletMap, Cmd Never )
mainInit flags =
( init { mapId = "mapid", tileUrl = flags.tileUrl } |> withRoutes flags.routes, Cmd.none )
in
Browser.element
{ init = mainInit
, update = \_ model -> ( model, Cmd.none )
, subscriptions = \_ -> Sub.none
, view = view
}
70 changes: 40 additions & 30 deletions assets/javascripts/app/LeafletMap.js
@@ -1,4 +1,7 @@
export default class LeafletMap {
import leaflet from 'leaflet';


export default class LeafletMap extends HTMLElement {
static get ROUTE_COLOR() {
return '#cc0605';
}
Expand All @@ -7,42 +10,17 @@ export default class LeafletMap {
return 4;
}

static getSwissMapBoundingBox(leaflet) {
static getSwissMapBoundingBox() {
return leaflet.latLngBounds(leaflet.latLng(45.398181, 5.140242), leaflet.latLng(48.230651, 11.47757));
}

constructor(leaflet, config, disabledServices = []) {

const map = leaflet.map(config.id);
this.leaflet = leaflet;
connectedCallback() {
const map = leaflet.map(this.getAttribute("map-id"));
this.markers = leaflet.featureGroup();

disabledServices.forEach(service => map[service].disable());

const route = leaflet.geoJson(config.routeGeoJson, {
style: {color: LeafletMap.ROUTE_COLOR, weight: LeafletMap.ROUTE_WEIGHT}
});
if (LeafletMap.getSwissMapBoundingBox(leaflet).contains(route.getBounds())) {
map.options.crs = leaflet.CRS.EPSG2056;
const greyTopoLayer = leaflet.tileLayer.swiss({layer: 'ch.swisstopo.pixelkarte-grau'});
const colorTopoLayer = leaflet.tileLayer.swiss().addTo(map);
const baseMaps = {
'Swiss Map': colorTopoLayer,
'Swiss Map in grey': greyTopoLayer,
};
leaflet.control.layers(baseMaps, {}).addTo(map);
} else {
leaflet.tileLayer(config.mapBoxTileUrl, {
attribution: '© <a href="https://www.mapbox.com/feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
tileSize: 512,
zoomOffset: -1,
}).addTo(map);
}
route.addTo(map);
map.fitBounds(route.getBounds());
this.map = map;
}

// TODO move this to a new `marker` element
updatePlaces(action, places) {

// are we in edit mode?
Expand Down Expand Up @@ -95,4 +73,36 @@ export default class LeafletMap {
}
}

class Route extends HTMLElement {
connectedCallback() {
const leafletMapNode = this.parentElement;
const map = leafletMapNode.map;
const route = leaflet.geoJson(JSON.parse(this.getAttribute("geojson")), {
style: {color: LeafletMap.ROUTE_COLOR, weight: LeafletMap.ROUTE_WEIGHT}
});

if (LeafletMap.getSwissMapBoundingBox().contains(route.getBounds())) {
map.options.crs = leaflet.CRS.EPSG2056;
const greyTopoLayer = leaflet.tileLayer.swiss({layer: 'ch.swisstopo.pixelkarte-grau'});
const colorTopoLayer = leaflet.tileLayer.swiss().addTo(map);
const baseMaps = {
'Swiss Map': colorTopoLayer,
'Swiss Map in grey': greyTopoLayer,
};
leaflet.control.layers(baseMaps, {}).addTo(map);
} else {
// TODO I don’t think this should belong to route
leaflet.tileLayer(leafletMapNode.getAttribute("tile-url"), {
attribution: '© <a href="https://www.mapbox.com/feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
tileSize: 512,
zoomOffset: -1,
}).addTo(map);
}
route.addTo(map);
map.fitBounds(route.getBounds());
}

}

customElements.define('leaflet-map', LeafletMap);
customElements.define('leaflet-route', Route);
2 changes: 2 additions & 0 deletions assets/javascripts/main.js
Expand Up @@ -20,5 +20,7 @@ HomeByTwo.LeafletMap = LeafletMap;
Object.assign(window, {HomeByTwo});

import {Elm} from '../elm/src/Checkpoints.elm';
import LeafletElm from '../elm/src/Leaflet.elm';

HomeByTwo.Elm = Elm;
HomeByTwo.LeafletElm = LeafletElm.Elm.Leaflet;
1 change: 1 addition & 0 deletions homebytwo/templates/routes/route/_route_map.html
@@ -1,6 +1,7 @@
{% if route.geom %}
<div class="section mrgv" id="map">
<h2>Route Map</h2>
<div id="leaflet-elm"></div>
<div class="map map--default" id="mapid"></div>
</div>
{% endif %}
13 changes: 6 additions & 7 deletions homebytwo/templates/routes/route/_route_map_script.html
Expand Up @@ -2,12 +2,11 @@

<script>
document.addEventListener('DOMContentLoaded', () => {

window.HomeByTwo.LeafletMap.map = new window.HomeByTwo.LeafletMap(window.HomeByTwo.L, {
id: 'mapid',
routeGeoJson: {{ route | geojsonfeature | safe }},
divIconClassName: 'placeIcon placeIcon--default',
mapBoxTileUrl: '{{ mapbox_tile_url }}'
}, ['scrollWheelZoom']);
// TODO don’t use a hardcoded ID
window.HomeByTwo.LeafletElm.init({node: document.getElementById("leaflet-elm"), flags: {
routes: ["{{ route|geojsonfeature|escapejs }}"],
tileUrl: "{{ mapbox_tile_url }}"
}
});
});
</script>
6 changes: 0 additions & 6 deletions homebytwo/templates/routes/route/route.html
Expand Up @@ -21,12 +21,6 @@
node: document.getElementById('elm-checkpoints'),
flags: JSON.parse(document.getElementById('checkpoints-config').textContent)
});
window.HomeByTwo.Elm.checkpointsApp.ports.updatePlaces.subscribe(message => {
requestAnimationFrame(() => {
const leafletMap = window.HomeByTwo.LeafletMap.map;
leafletMap.updatePlaces(message.action, message.places);
});
});
});
</script>
{{ checkpoints_config|json_script:"checkpoints-config" }}
Expand Down

0 comments on commit bd98f5f

Please sign in to comment.