leaflet/src/layer.ml

228 lines
6.8 KiB
OCaml
Raw Normal View History

2022-04-12 13:46:37 +02:00
(* BSD-2-Clause License *)
2022-04-09 22:21:22 +02:00
type _ t =
| Basic : Jv.t -> [> `Basic ] t
| Geojson : Jv.t -> [> `Geojson ] t
| Marker : Jv.t -> [> `Marker ] t
| Tile : Jv.t -> [> `Tile ] t
2022-04-08 13:21:20 +02:00
2022-06-20 06:52:05 +02:00
type _ sub =
| Basic : [> `Basic ] sub
| Geojson : [> `Geojson ] sub
| Marker : [> `Marker ] sub
| Tile : [> `Tile ] sub
2022-04-09 22:21:22 +02:00
(** Basic layers *)
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let add_to : type kind. Map.t -> kind t -> unit =
fun map -> function
| Basic l | Geojson l | Marker l | Tile l ->
let (_ : Jv.t) = Jv.call l "addTo" [| Map.to_jv map |] in
()
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let remove : type kind. kind t -> unit = function
| Basic l | Geojson l | Marker l | Tile l ->
let (_ : Jv.t) = Jv.call l "remove" [||] in
()
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let remove_from : type kind. Map.t -> kind t -> unit =
fun map -> function
| Basic l | Geojson l | Marker l | Tile l ->
let (_ : Jv.t) = Jv.call l "removeFrom" [| Map.to_jv map |] in
()
2022-04-08 13:21:20 +02:00
let bind_popup : type kind. Popup.t -> kind t -> unit =
fun popup -> function
2022-06-20 10:05:35 +02:00
| Basic layer | Geojson layer | Marker layer | Tile layer ->
let (_ : Jv.t) = Jv.call layer "bindPopup" [| Popup.to_jv popup |] in
2022-04-09 22:21:22 +02:00
()
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let unbind_popup : type kind. kind t -> unit = function
| Basic l | Geojson l | Marker l | Tile l ->
let (_ : Jv.t) = Jv.call l "unbindPopup" [||] in
()
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let open_popup : type kind. kind t -> unit = function
| Basic l | Geojson l | Marker l | Tile l ->
let (_ : Jv.t) = Jv.call l "openPopup" [||] in
()
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let close_popup : type kind. kind t -> unit = function
| Basic l | Geojson l | Marker l | Tile l ->
let (_ : Jv.t) = Jv.call l "closePopup" [||] in
()
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let get_popup : type kind. kind t -> Popup.t = function
| Basic l | Geojson l | Marker l | Tile l ->
Jv.call l "getPopup" [||] |> Popup.of_jv
2022-04-08 13:21:20 +02:00
2022-04-09 22:21:22 +02:00
let to_jv : type kind. kind t -> Jv.t = function
| Basic l | Geojson l | Marker l | Tile l -> l
2022-06-20 06:52:05 +02:00
let of_jv : type kind. kind sub -> Jv.t -> kind t =
fun tag l ->
match tag with
| Basic -> Basic l
| Geojson -> Geojson l
| Marker -> Marker l
| Tile -> Tile l
let on : type kind. kind Event.sub -> (kind Event.t -> 'b) -> 'c t -> unit =
fun event handler layer ->
let name = Event.sub_to_string event in
let handler v = handler @@ Event.of_jv event v in
let (_ : Jv.t) =
Jv.call (to_jv layer) "on" [| Jv.of_string name; Jv.repr handler |]
in
()
2022-04-09 22:21:22 +02:00
(** Geojson layers *)
2022-06-20 09:17:23 +02:00
type geojson_opt =
2022-06-20 11:04:44 +02:00
| Point_to_layer of (Jv.t -> Latlng.t -> [ `Marker ] t)
2022-06-20 09:17:23 +02:00
| Style of (Jv.t -> unit)
| On_each_feature of (Jv.t -> [ `Geojson ] t -> unit)
| Filter of (Jv.t -> bool)
| Coords_to_latlng of (Jv.t -> Latlng.t)
| Markers_inherit_options of bool
let geojson_opt_to_string = function
| Point_to_layer _ -> "pointToLayer"
| Style _ -> "style"
| On_each_feature _ -> "onEachFeature"
| Filter _ -> "filter"
| Coords_to_latlng _ -> "coordsToLatLng"
| Markers_inherit_options _ -> "markersInheritOptions"
let geojson_opt_to_jv = function
| Markers_inherit_options b -> Jv.of_bool b
2022-06-20 11:04:44 +02:00
| Point_to_layer f ->
(* the marker returned by `pointToLayer` is used internally by leaflet so we neet to unwrap it to a Jv.t *)
Jv.repr (fun geojsonpoint latlng -> to_jv @@ f geojsonpoint latlng)
2022-06-20 09:17:23 +02:00
| Style f -> Jv.repr f
2022-06-20 10:05:35 +02:00
| On_each_feature f ->
(* we need to wrap the Jv.t *)
let f feature jv = jv |> of_jv Geojson |> f feature in
Jv.repr f
2022-06-20 09:17:23 +02:00
| Filter f -> Jv.repr f
| Coords_to_latlng f -> Jv.repr f
let create_geojson : Jv.t -> geojson_opt list -> [ `Geojson ] t =
fun geojson options ->
let l =
Array.of_list
@@ List.map
(fun o -> (geojson_opt_to_string o, geojson_opt_to_jv o))
options
in
let jv_t = Jv.call Global.leaflet "geoJSON" [| geojson; Jv.obj l |] in
2022-04-09 22:21:22 +02:00
Geojson jv_t
2022-11-24 19:22:18 +01:00
(** Tile layers *)
2024-01-29 22:49:31 +01:00
type tile_layer_opt =
| Min_zoom of int
| Max_zoom of int
| Subdomains of string array
| Error_tile_url of string
| Zoom_offset of int
| Tms of bool
| Zoom_reverse of bool
| Detect_retina of bool
2024-01-30 00:20:36 +01:00
| (* TODO allow string for those two
"Whether the crossOrigin attribute will be added to the tiles. If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data. Refer to CORS Settings for valid String values."
*)
Cross_origin of bool
2024-01-29 22:49:31 +01:00
| Referrer_policy of bool
2024-01-30 00:20:36 +01:00
| (* GridLayer options *)
Tile_size of Point.t
| Opacity of float
| Update_when_idle of bool
| Update_when_zooming of bool
| Update_interval of int
| Z_index of int
| Bounds of (* LatLngBounds *) Latlng.t * Latlng.t
| Max_native_zoom of int
| Min_native_zoom of int
| No_wrap of bool
| Pane of string
| Class_name of string
| Keep_buffer of int
2024-01-29 22:49:31 +01:00
let tile_layer_opt_to_string = function
| Min_zoom _ -> "minZoom"
| Max_zoom _ -> "maxZoom"
| Subdomains _ -> "subdomains"
| Error_tile_url _ -> "errorTileUrl"
| Zoom_offset _ -> "zoomOffset"
| Tms _ -> "tms"
| Zoom_reverse _ -> "zoomReverse"
| Detect_retina _ -> "detectRetina"
| Cross_origin _ -> "crossOrigin"
| Referrer_policy _ -> "referrerPolicy"
2024-01-30 00:20:36 +01:00
| Tile_size _ -> "tileSize"
| Opacity _ -> "opacity"
| Update_when_idle _ -> "updateWhenIdle"
| Update_when_zooming _ -> "updateWhenZooming"
| Update_interval _ -> "updateInterval"
| Z_index _ -> "zIndex"
| Bounds _ -> "bounds"
| Max_native_zoom _ -> "maxNativeZoom"
| Min_native_zoom _ -> "minNativeZoom"
| No_wrap _ -> "noWrap"
| Pane _ -> "pane"
| Class_name _ -> "className"
| Keep_buffer _ -> "keepBuffer"
2024-01-29 22:49:31 +01:00
let tile_layer_opt_to_jv = function
2024-01-30 00:20:36 +01:00
| Min_zoom o
| Max_zoom o
| Zoom_offset o
| Update_interval o
| Z_index o
| Keep_buffer o
| Min_native_zoom o
| Max_native_zoom o ->
Jv.of_int o
2024-01-29 22:49:31 +01:00
| Tms o
| Zoom_reverse o
| Detect_retina o
| Cross_origin o
2024-01-30 00:20:36 +01:00
| Referrer_policy o
| Update_when_idle o
| Update_when_zooming o
| No_wrap o ->
2024-01-29 22:49:31 +01:00
Jv.of_bool o
2024-01-30 00:20:36 +01:00
| Error_tile_url o | Pane o | Class_name o -> Jv.of_string o
2024-01-29 22:49:31 +01:00
| Subdomains o -> Jv.of_array Jv.of_string o
2024-01-30 00:20:36 +01:00
| Opacity o -> Jv.of_float o
| Tile_size o -> Point.to_jv o
| Bounds (a, b) ->
(* create the actual LatlngBounds from the pair *)
Jv.call Global.leaflet "latLngBounds" [| Latlng.to_jv a; Latlng.to_jv b |]
2024-01-29 22:49:31 +01:00
let create_tile :
string -> attribution:string -> tile_layer_opt list -> [ `Tile ] t =
fun url ~attribution options ->
let arr =
Array.of_list
@@ ("attribution", Jv.of_string attribution)
:: List.map
(fun o -> (tile_layer_opt_to_string o, tile_layer_opt_to_jv o))
options
2022-11-24 19:22:18 +01:00
in
let jv_t =
2024-01-29 22:49:31 +01:00
Jv.call Global.leaflet "tileLayer" [| Jv.of_string url; Jv.obj arr |]
2022-11-24 19:22:18 +01:00
in
Tile jv_t
2024-01-29 22:49:31 +01:00
let create_tile_osm : tile_layer_opt list -> [ `Tile ] t =
fun options ->
let url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" in
let attribution =
"&copy; <a \
href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> \
contributors"
in
create_tile url ~attribution options