leaflet/src/layer.ml

245 lines
7.4 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
2024-01-30 00:48:37 +01:00
| Vector : Jv.t -> [> `Vector ] 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
2024-01-30 00:48:37 +01:00
| Vector : [> `Vector ] sub
2022-06-20 06:52:05 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l ->
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l ->
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l ->
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic layer | Geojson layer | Marker layer | Tile layer | Vector 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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l ->
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l ->
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l ->
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l ->
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Basic l | Geojson l | Marker l | Tile l | Vector l -> l
2022-04-09 22:21:22 +02:00
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
2024-01-30 00:48:37 +01:00
| Vector -> Vector l
2022-06-20 06:52:05 +02:00
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
2024-01-30 16:55:19 +01:00
let create_geojson : Jv.t -> geojson_opt array -> [ `Geojson ] t =
2022-06-20 09:17:23 +02:00
fun geojson options ->
let l =
2024-01-30 16:55:19 +01:00
Array.map (fun o -> (geojson_opt_to_string o, geojson_opt_to_jv o)) options
2022-06-20 09:17:23 +02:00
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 :
2024-01-30 16:55:19 +01:00
string -> attribution:string -> tile_layer_opt array -> [ `Tile ] t =
2024-01-29 22:49:31 +01:00
fun url ~attribution options ->
let arr =
2024-01-30 16:55:19 +01:00
Array.append
[| ("attribution", Jv.of_string attribution) |]
(Array.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
2024-01-30 16:55:19 +01:00
let create_tile_osm : tile_layer_opt array -> [ `Tile ] t =
2024-01-29 22:49:31 +01:00
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
2024-01-30 00:48:37 +01:00
(* Vector Layers *)
2024-01-30 18:45:24 +01:00
(* TODO add options *)
2024-01-30 16:55:19 +01:00
let create_polyline : Latlng.t array -> [ `Vector ] t =
2024-01-30 00:48:37 +01:00
fun l ->
2024-01-30 16:55:19 +01:00
let l = Jv.of_array Latlng.to_jv l in
2024-01-30 00:48:37 +01:00
let jv_t = Jv.call Global.leaflet "polyline" [| l |] in
Vector jv_t
2024-01-30 18:45:24 +01:00
let create_circle_marker : Latlng.t -> float -> [ `Vector ] t =
fun center radius ->
let center = Latlng.to_jv center in
let arr = [| ("radius", Jv.of_float radius) |] in
let jv_t = Jv.call Global.leaflet "circleMarker" [| center; Jv.obj arr |] in
Vector jv_t