├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── examples ├── basic │ ├── Cargo.toml │ ├── README.md │ ├── index.html │ └── src │ │ └── lib.rs ├── leaflet-dioxus-example │ ├── .gitignore │ ├── Cargo.toml │ ├── Dioxus.toml │ ├── README.md │ ├── assets │ │ ├── favicon.ico │ │ └── main.css │ └── src │ │ └── main.rs └── yew-component │ ├── Cargo.toml │ ├── README.md │ ├── dist │ └── index.html │ ├── index.html │ ├── scss │ ├── normalize.scss │ └── style.scss │ └── src │ ├── components.rs │ ├── components │ ├── control.rs │ └── map_component.rs │ └── main.rs └── src ├── control.rs ├── control └── zoom.rs ├── crs.rs ├── div_icon.rs ├── div_overlay.rs ├── event.rs ├── evented.rs ├── feature_group.rs ├── geo_json.rs ├── grid_layer.rs ├── handler.rs ├── icon.rs ├── lat_lng.rs ├── lat_lng_bounds.rs ├── layer.rs ├── layer_control.rs ├── layer_group.rs ├── lib.rs ├── map ├── events.rs ├── geolocation.rs ├── location_event.rs ├── mod.rs └── other.rs ├── marker.rs ├── point.rs ├── popup.rs ├── raster ├── image_overlay.rs ├── mod.rs ├── tile_layer.rs ├── tile_layer_wms.rs └── video_overlay.rs ├── shapes ├── circle.rs ├── circle_marker.rs ├── mod.rs ├── path.rs ├── polygon.rs ├── polyline.rs └── rectangle.rs ├── tooltip.rs └── util.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | examples/yew-components/dist 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leaflet" 3 | version = "0.4.1" 4 | authors = ["slowtec GmbH ", "Lewin Probst ", "Daniel Santana "] 5 | license = "MIT/Apache-2.0" 6 | description = "A wasm-bindgen wrapper for Leaflet.js" 7 | homepage = "https://github.com/slowtec/leaflet-rs" 8 | repository = "https://github.com/slowtec/leaflet-rs" 9 | edition = "2021" 10 | readme = "README.md" 11 | rust-version = "1.75" 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2" 15 | js-sys = "0.3" 16 | paste = "1" 17 | url = "2" 18 | 19 | [dependencies.web-sys] 20 | version = "0.3" 21 | features = ["Event", "HtmlElement", "MouseEvent"] 22 | 23 | [badges] 24 | maintenance = { status = "actively-developed" } 25 | 26 | [lints.clippy] 27 | pedantic = { level = "warn", priority = -1 } 28 | missing_const_for_fn = "warn" 29 | 30 | # The error types returned should be self-explanatory. 31 | missing_errors_doc = "allow" 32 | 33 | # Repetitions of module/type names occur frequently when using many 34 | # modules for keeping the size of the source files handy. 35 | # Often types have the same name as their parent module. 36 | module_name_repetitions = "allow" 37 | 38 | # Allow #[wasm_bindgen] to create empty docs 39 | empty_docs = "allow" 40 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 - 2021 slowtec GmbH 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 - 2021 slowtec GmbH 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # leaflet-rs 2 | 3 | A [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) 4 | wrapper for 5 | [Leaflet.js](https://leafletjs.com/) 6 | 7 | [![Crates.io](https://img.shields.io/crates/v/leaflet.svg)](https://crates.io/crates/leaflet) 8 | [![Docs.rs](https://docs.rs/leaflet/badge.svg)](https://docs.rs/leaflet/) 9 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE-MIT) 10 | [![Apache 2.0 licensed](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](./LICENSE-APACHE) 11 | 12 | ## Usage 13 | 14 | ```toml 15 | [dependencies] 16 | leaflet = "0.4" 17 | ``` 18 | 19 | ## Example 20 | 21 | See: 22 | 23 | - Basic example: [`examples/basic`](https://github.com/slowtec/leaflet-rs/tree/master/examples/basic) 24 | - Usage in yew component: [`examples/yew-component`](https://github.com/slowtec/leaflet-rs/tree/master/examples/yew-component) 25 | - Usage with Dioxus: [`examples/leaflet-dioxus-example`](https://github.com/slowtec/leaflet-rs/tree/master/examples/leaflet-dioxus-example) 26 | - Usage with leptos: [headless-studio/leptos-leaflet](https://github.com/headless-studio/leptos-leaflet) 27 | 28 | ## License 29 | 30 | Copyright (c) 2020 - 2024 [slowtec GmbH](https://slowtec.de) 31 | -------------------------------------------------------------------------------- /examples/basic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leaflet-rs-example" 3 | version = "0.1.0" 4 | authors = ["The leaflet-rs Developers"] 5 | license = "MIT/Apache-2.0" 6 | description = "An example using leaflet-rs" 7 | homepage = "https://github.com/slowtec/leaflet-rs" 8 | repository = "https://github.com/slowtec/leaflet-rs" 9 | edition = "2021" 10 | publish = false 11 | 12 | [lib] 13 | crate-type = ["cdylib"] 14 | 15 | [dependencies] 16 | leaflet = { path = "../.." } 17 | # Your project would instead do: 18 | # leaflet = "0.4.0" 19 | 20 | gloo-events = "0.1" 21 | js-sys = "0.3" 22 | wasm-bindgen = "0.2" 23 | 24 | [dependencies.web-sys] 25 | version = "0.3" 26 | features = [ 27 | "console", 28 | "Document", 29 | "HtmlAnchorElement", 30 | "Window" 31 | ] 32 | 33 | [profile.release] 34 | lto = true 35 | opt-level = 'z' 36 | codegen-units = 1 37 | -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Leaflet-rs example 2 | 3 | ## How to build 4 | 5 | ``` 6 | cargo install wasm-pack https 7 | # in current directory, so: examples/basic 8 | wasm-pack build --target web 9 | http 10 | ``` 11 | 12 | Then open http://localhost:8000 13 | -------------------------------------------------------------------------------- /examples/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 16 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /examples/basic/src/lib.rs: -------------------------------------------------------------------------------- 1 | use gloo_events::EventListener; 2 | use js_sys::Array; 3 | use leaflet::{ 4 | Circle, CircleOptions, Control, ControlOptions, LatLng, LatLngBounds, Map, MapOptions, Polygon, 5 | Polyline, PolylineOptions, Rectangle, TileLayer, 6 | }; 7 | use wasm_bindgen::{prelude::*, JsCast}; 8 | use web_sys::{console, window, HtmlAnchorElement}; 9 | 10 | // Called when the wasm module is instantiated 11 | #[wasm_bindgen(start)] 12 | pub fn main() -> Result<(), JsValue> { 13 | console::log_1(&"Running Leaflet example code in Rust.".into()); 14 | 15 | let options = MapOptions::default(); 16 | let map = Map::new("map", &options); 17 | map.set_view(&LatLng::new(63.5, 10.5), 5.0); 18 | 19 | add_tile_layer(&map); 20 | add_polyline(&map); 21 | add_polygon(&map); 22 | add_rectangle(&map); 23 | add_circle(&map); 24 | add_circle_with_options(&map); 25 | add_control(&map); 26 | 27 | Ok(()) 28 | } 29 | 30 | fn add_tile_layer(map: &Map) { 31 | TileLayer::new("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").add_to(map); 32 | } 33 | 34 | fn add_polyline(map: &Map) { 35 | let options = PolylineOptions::default(); 36 | Polyline::new_with_options( 37 | &[ 38 | LatLng::new(63.25, 11.25), 39 | LatLng::new(63.75, 11.75), 40 | LatLng::new(63.5, 12.0), 41 | ] 42 | .iter() 43 | .map(JsValue::from) 44 | .collect::(), 45 | &options, 46 | ) 47 | .add_to(map); 48 | } 49 | 50 | fn add_polygon(map: &Map) { 51 | Polygon::new( 52 | &[ 53 | LatLng::new(63.25, 12.25), 54 | LatLng::new(63.75, 12.75), 55 | LatLng::new(63.5, 13.0), 56 | ] 57 | .iter() 58 | .map(JsValue::from) 59 | .collect::(), 60 | ) 61 | .add_to(map); 62 | } 63 | 64 | fn add_rectangle(map: &Map) { 65 | Rectangle::new(&LatLngBounds::new( 66 | &LatLng::new(63.25, 10.25), 67 | &LatLng::new(63.75, 10.75), 68 | )) 69 | .add_to(map); 70 | } 71 | 72 | fn add_circle(map: &Map) { 73 | Circle::new(&LatLng::new(63.25, 13.25)).add_to(map); 74 | } 75 | 76 | fn add_circle_with_options(map: &Map) { 77 | let options = CircleOptions::default(); 78 | options.set_radius(4000.0); 79 | Circle::new_with_options(&LatLng::new(63.25, 13.35), &options).add_to(map); 80 | } 81 | 82 | fn add_control(map: &Map) { 83 | let options = ControlOptions::default(); 84 | options.set_position("topleft".to_string()); 85 | let control_button = Control::new(&options); 86 | 87 | // This callback must return a HTML div representing the control button. 88 | let on_add = |_: &_| { 89 | let document = window() 90 | .expect("Unable to get browser window") 91 | .document() 92 | .expect("Unable to get browser document"); 93 | 94 | let container = document 95 | .create_element("div") 96 | .expect("Unable to create div"); 97 | 98 | container.set_class_name("leaflet-bar"); 99 | 100 | let link = document 101 | .create_element("a") 102 | .expect("Unable to create link") 103 | .dyn_into::() 104 | .expect("Unable to cast to HtmlAnchorElement"); 105 | 106 | link.set_href("#"); 107 | link.set_inner_html("⬤"); 108 | link.set_title("Create a new foobar."); 109 | 110 | let on_click = EventListener::new(&link, "click", |_| { 111 | console::log_1(&"Control button click.".into()); 112 | }); 113 | 114 | on_click.forget(); 115 | 116 | container 117 | .append_child(&link) 118 | .expect("Unable to add child element"); 119 | 120 | container.dyn_into().unwrap() 121 | }; 122 | 123 | control_button.on_add(on_add); 124 | control_button.add_to(map); 125 | } 126 | -------------------------------------------------------------------------------- /examples/leaflet-dioxus-example/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /dist/ 5 | /static/ 6 | /.dioxus/ 7 | 8 | # this file will generate by tailwind: 9 | /assets/tailwind.css 10 | 11 | # These are backup files generated by rustfmt 12 | **/*.rs.bk 13 | -------------------------------------------------------------------------------- /examples/leaflet-dioxus-example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leaflet-dioxus-example" 3 | version = "0.1.0" 4 | authors = ["The leaflet-rs Developers"] 5 | license = "MIT/Apache-2.0" 6 | description = "An example using leaflet-rs in yew.rs component" 7 | homepage = "https://github.com/slowtec/leaflet-rs" 8 | repository = "https://github.com/slowtec/leaflet-rs" 9 | edition = "2021" 10 | publish = false 11 | 12 | [dependencies] 13 | 14 | dioxus = { version = "0.5", features = ["web"] } 15 | dioxus-logger = "0.5.1" 16 | gloo-utils = "0.2.0" 17 | leaflet = { path = "../../" } 18 | web-sys = "0.3.69" 19 | -------------------------------------------------------------------------------- /examples/leaflet-dioxus-example/Dioxus.toml: -------------------------------------------------------------------------------- 1 | [application] 2 | 3 | # App (Project) Name 4 | name = "leaflet-dioxus-example" 5 | 6 | # Dioxus App Default Platform 7 | # web, desktop, fullstack 8 | default_platform = "web" 9 | 10 | # `build` & `serve` dist path 11 | out_dir = "dist" 12 | 13 | # resource (assets) file folder 14 | asset_dir = "assets" 15 | 16 | [web.app] 17 | 18 | # HTML title tag content 19 | title = "leaflet-dioxus-example" 20 | 21 | [web.watcher] 22 | 23 | # when watcher trigger, regenerate the `index.html` 24 | reload_html = true 25 | 26 | # which files or dirs will be watcher monitoring 27 | watch_path = ["src", "assets"] 28 | 29 | # include `assets` in web platform 30 | [web.resource] 31 | 32 | # CSS style file 33 | 34 | style = [ 35 | "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css", 36 | "main.css", 37 | ] 38 | 39 | # Javascript code file 40 | script = ["https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"] 41 | 42 | [web.resource.dev] 43 | 44 | # Javascript code file 45 | # serve: [dev-server] only 46 | script = [] 47 | -------------------------------------------------------------------------------- /examples/leaflet-dioxus-example/README.md: -------------------------------------------------------------------------------- 1 | # Leaflet-rs in Dioxus example 2 | 3 | Run the following command in the root of the project to start the Dioxus dev server: 4 | 5 | ```bash 6 | dx serve --hot-reload 7 | ``` 8 | 9 | - Open the browser to 10 | 11 | -------------------------------------------------------------------------------- /examples/leaflet-dioxus-example/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/slowtec/leaflet-rs/0ab7f1d39f65ffdb038ed13fe6c08151c56e3849/examples/leaflet-dioxus-example/assets/favicon.ico -------------------------------------------------------------------------------- /examples/leaflet-dioxus-example/assets/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } 4 | 5 | #map { 6 | width: 100%; 7 | height: 100vh; 8 | } 9 | -------------------------------------------------------------------------------- /examples/leaflet-dioxus-example/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | 3 | use dioxus::prelude::*; 4 | use dioxus_logger::tracing::{info, Level}; 5 | use gloo_utils::document; 6 | use leaflet::{Map, MapOptions, Marker, TileLayer}; 7 | use web_sys::{wasm_bindgen::JsCast, HtmlElement}; 8 | 9 | #[component] 10 | fn App() -> Element { 11 | use_effect(move || { 12 | const GREENWICH_MERIDIAN: (f64, f64) = (51.477806, -0.001472); 13 | 14 | let container: HtmlElement = document() 15 | .get_element_by_id("map") 16 | .unwrap() 17 | .dyn_into() 18 | .unwrap(); 19 | 20 | let map = Map::new_with_element(&container, &MapOptions::default()); 21 | 22 | TileLayer::new("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").add_to(&map); 23 | 24 | map.set_view(&GREENWICH_MERIDIAN.into(), 14.0); 25 | 26 | Marker::new(&GREENWICH_MERIDIAN.into()).add_to(&map); 27 | }); 28 | 29 | rsx! { 30 | div { id: "map" } 31 | } 32 | } 33 | 34 | fn main() { 35 | // Init logger 36 | dioxus_logger::init(Level::INFO).expect("failed to init logger"); 37 | info!("starting app"); 38 | launch(App); 39 | } 40 | -------------------------------------------------------------------------------- /examples/yew-component/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leaflet-rs-example-yew-component" 3 | version = "0.1.0" 4 | authors = ["The leaflet-rs Developers"] 5 | license = "MIT/Apache-2.0" 6 | description = "An example using leaflet-rs in yew.rs component" 7 | homepage = "https://github.com/slowtec/leaflet-rs" 8 | repository = "https://github.com/slowtec/leaflet-rs" 9 | edition = "2021" 10 | publish = false 11 | 12 | [dependencies] 13 | yew = { version = "0.21.0", features = ["csr"] } 14 | implicit-clone = "0.3.6" 15 | leaflet = { path = "../../" } 16 | wasm-bindgen = "0.2" 17 | gloo-console = "0.2" 18 | gloo-utils = "0.1" 19 | 20 | [dependencies.web-sys] 21 | version = "0.3" 22 | features = ["HtmlAnchorElement", "console", "Window", "Document"] 23 | -------------------------------------------------------------------------------- /examples/yew-component/README.md: -------------------------------------------------------------------------------- 1 | # Leaflet-rs in yew.rs example 2 | 3 | An example that shows how to use library to use Leaflet within 4 | a [yew.rs](https://yew.rs) component. 5 | 6 | ## How to run the example 7 | 8 | ``` 9 | cargo install trunk 10 | # in current directory, so: src/examples/yew-component 11 | trunk serve 12 | ``` 13 | 14 | Then open http://localhost:8080 15 | 16 | ## To build 17 | 18 | ``` 19 | trunk build --release 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/yew-component/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | leaflet-rs yew component example 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/yew-component/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | leaflet-rs yew component example 6 | 12 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/yew-component/scss/normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Render the `main` element consistently in IE. 29 | */ 30 | 31 | main { 32 | display: block; 33 | } 34 | 35 | /** 36 | * Correct the font size and margin on `h1` elements within `section` and 37 | * `article` contexts in Chrome, Firefox, and Safari. 38 | */ 39 | 40 | h1 { 41 | font-size: 2em; 42 | margin: 0.67em 0; 43 | } 44 | 45 | /* Grouping content 46 | ========================================================================== */ 47 | 48 | /** 49 | * 1. Add the correct box sizing in Firefox. 50 | * 2. Show the overflow in Edge and IE. 51 | */ 52 | 53 | hr { 54 | box-sizing: content-box; /* 1 */ 55 | height: 0; /* 1 */ 56 | overflow: visible; /* 2 */ 57 | } 58 | 59 | /** 60 | * 1. Correct the inheritance and scaling of font size in all browsers. 61 | * 2. Correct the odd `em` font sizing in all browsers. 62 | */ 63 | 64 | pre { 65 | font-family: monospace, monospace; /* 1 */ 66 | font-size: 1em; /* 2 */ 67 | } 68 | 69 | /* Text-level semantics 70 | ========================================================================== */ 71 | 72 | /** 73 | * Remove the gray background on active links in IE 10. 74 | */ 75 | 76 | a { 77 | background-color: transparent; 78 | } 79 | 80 | /** 81 | * 1. Remove the bottom border in Chrome 57- 82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 83 | */ 84 | 85 | abbr[title] { 86 | border-bottom: none; /* 1 */ 87 | text-decoration: underline; /* 2 */ 88 | text-decoration: underline dotted; /* 2 */ 89 | } 90 | 91 | /** 92 | * Add the correct font weight in Chrome, Edge, and Safari. 93 | */ 94 | 95 | b, 96 | strong { 97 | font-weight: bolder; 98 | } 99 | 100 | /** 101 | * 1. Correct the inheritance and scaling of font size in all browsers. 102 | * 2. Correct the odd `em` font sizing in all browsers. 103 | */ 104 | 105 | code, 106 | kbd, 107 | samp { 108 | font-family: monospace, monospace; /* 1 */ 109 | font-size: 1em; /* 2 */ 110 | } 111 | 112 | /** 113 | * Add the correct font size in all browsers. 114 | */ 115 | 116 | small { 117 | font-size: 80%; 118 | } 119 | 120 | /** 121 | * Prevent `sub` and `sup` elements from affecting the line height in 122 | * all browsers. 123 | */ 124 | 125 | sub, 126 | sup { 127 | font-size: 75%; 128 | line-height: 0; 129 | position: relative; 130 | vertical-align: baseline; 131 | } 132 | 133 | sub { 134 | bottom: -0.25em; 135 | } 136 | 137 | sup { 138 | top: -0.5em; 139 | } 140 | 141 | /* Embedded content 142 | ========================================================================== */ 143 | 144 | /** 145 | * Remove the border on images inside links in IE 10. 146 | */ 147 | 148 | img { 149 | border-style: none; 150 | } 151 | 152 | /* Forms 153 | ========================================================================== */ 154 | 155 | /** 156 | * 1. Change the font styles in all browsers. 157 | * 2. Remove the margin in Firefox and Safari. 158 | */ 159 | 160 | button, 161 | input, 162 | optgroup, 163 | select, 164 | textarea { 165 | font-family: inherit; /* 1 */ 166 | font-size: 100%; /* 1 */ 167 | line-height: 1.15; /* 1 */ 168 | margin: 0; /* 2 */ 169 | } 170 | 171 | /** 172 | * Show the overflow in IE. 173 | * 1. Show the overflow in Edge. 174 | */ 175 | 176 | button, 177 | input { 178 | /* 1 */ 179 | overflow: visible; 180 | } 181 | 182 | /** 183 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 184 | * 1. Remove the inheritance of text transform in Firefox. 185 | */ 186 | 187 | button, 188 | select { 189 | /* 1 */ 190 | text-transform: none; 191 | } 192 | 193 | /** 194 | * Correct the inability to style clickable types in iOS and Safari. 195 | */ 196 | 197 | button, 198 | [type="button"], 199 | [type="reset"], 200 | [type="submit"] { 201 | -webkit-appearance: button; 202 | } 203 | 204 | /** 205 | * Remove the inner border and padding in Firefox. 206 | */ 207 | 208 | button::-moz-focus-inner, 209 | [type="button"]::-moz-focus-inner, 210 | [type="reset"]::-moz-focus-inner, 211 | [type="submit"]::-moz-focus-inner { 212 | border-style: none; 213 | padding: 0; 214 | } 215 | 216 | /** 217 | * Restore the focus styles unset by the previous rule. 218 | */ 219 | 220 | button:-moz-focusring, 221 | [type="button"]:-moz-focusring, 222 | [type="reset"]:-moz-focusring, 223 | [type="submit"]:-moz-focusring { 224 | outline: 1px dotted ButtonText; 225 | } 226 | 227 | /** 228 | * Correct the padding in Firefox. 229 | */ 230 | 231 | fieldset { 232 | padding: 0.35em 0.75em 0.625em; 233 | } 234 | 235 | /** 236 | * 1. Correct the text wrapping in Edge and IE. 237 | * 2. Correct the color inheritance from `fieldset` elements in IE. 238 | * 3. Remove the padding so developers are not caught out when they zero out 239 | * `fieldset` elements in all browsers. 240 | */ 241 | 242 | legend { 243 | box-sizing: border-box; /* 1 */ 244 | color: inherit; /* 2 */ 245 | display: table; /* 1 */ 246 | max-width: 100%; /* 1 */ 247 | padding: 0; /* 3 */ 248 | white-space: normal; /* 1 */ 249 | } 250 | 251 | /** 252 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 253 | */ 254 | 255 | progress { 256 | vertical-align: baseline; 257 | } 258 | 259 | /** 260 | * Remove the default vertical scrollbar in IE 10+. 261 | */ 262 | 263 | textarea { 264 | overflow: auto; 265 | } 266 | 267 | /** 268 | * 1. Add the correct box sizing in IE 10. 269 | * 2. Remove the padding in IE 10. 270 | */ 271 | 272 | [type="checkbox"], 273 | [type="radio"] { 274 | box-sizing: border-box; /* 1 */ 275 | padding: 0; /* 2 */ 276 | } 277 | 278 | /** 279 | * Correct the cursor style of increment and decrement buttons in Chrome. 280 | */ 281 | 282 | [type="number"]::-webkit-inner-spin-button, 283 | [type="number"]::-webkit-outer-spin-button { 284 | height: auto; 285 | } 286 | 287 | /** 288 | * 1. Correct the odd appearance in Chrome and Safari. 289 | * 2. Correct the outline style in Safari. 290 | */ 291 | 292 | [type="search"] { 293 | -webkit-appearance: textfield; /* 1 */ 294 | outline-offset: -2px; /* 2 */ 295 | } 296 | 297 | /** 298 | * Remove the inner padding in Chrome and Safari on macOS. 299 | */ 300 | 301 | [type="search"]::-webkit-search-decoration { 302 | -webkit-appearance: none; 303 | } 304 | 305 | /** 306 | * 1. Correct the inability to style clickable types in iOS and Safari. 307 | * 2. Change font properties to `inherit` in Safari. 308 | */ 309 | 310 | ::-webkit-file-upload-button { 311 | -webkit-appearance: button; /* 1 */ 312 | font: inherit; /* 2 */ 313 | } 314 | 315 | /* Interactive 316 | ========================================================================== */ 317 | 318 | /* 319 | * Add the correct display in Edge, IE 10+, and Firefox. 320 | */ 321 | 322 | details { 323 | display: block; 324 | } 325 | 326 | /* 327 | * Add the correct display in all browsers. 328 | */ 329 | 330 | summary { 331 | display: list-item; 332 | } 333 | 334 | /* Misc 335 | ========================================================================== */ 336 | 337 | /** 338 | * Add the correct display in IE 10+. 339 | */ 340 | 341 | template { 342 | display: none; 343 | } 344 | 345 | /** 346 | * Add the correct display in IE 10. 347 | */ 348 | 349 | [hidden] { 350 | display: none; 351 | } 352 | -------------------------------------------------------------------------------- /examples/yew-component/scss/style.scss: -------------------------------------------------------------------------------- 1 | @import "normalize"; 2 | 3 | html, 4 | body { 5 | box-sizing: border-box; 6 | } 7 | 8 | body { 9 | // those styles are irrelevant, just here for nicer presentation 10 | display: flex; 11 | flex-direction: column; 12 | height: 400px; 13 | width: 800px; 14 | margin: 2em auto; 15 | 16 | .map { 17 | height: 400px; 18 | } 19 | 20 | .component-container { 21 | border-radius: 0.5em; 22 | padding: 1em; 23 | } 24 | 25 | .map-container { 26 | border: 1px solid red; 27 | margin-bottom: 1em; 28 | } 29 | 30 | .control { 31 | text-align: center; 32 | border: 1px solid green; 33 | 34 | button { 35 | margin: 0.5em; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/yew-component/src/components.rs: -------------------------------------------------------------------------------- 1 | pub mod control; 2 | pub mod map_component; 3 | -------------------------------------------------------------------------------- /examples/yew-component/src/components/control.rs: -------------------------------------------------------------------------------- 1 | use super::map_component::City; 2 | use gloo_console::log; 3 | use yew::{html::ImplicitClone, prelude::*}; 4 | 5 | pub enum Msg { 6 | CityChosen(City), 7 | } 8 | 9 | pub struct Control { 10 | cities: Vec, 11 | } 12 | 13 | #[derive(PartialEq, Clone)] 14 | pub struct Cities { 15 | pub list: Vec, 16 | } 17 | 18 | impl ImplicitClone for Cities {} 19 | 20 | #[derive(PartialEq, Properties, Clone)] 21 | pub struct Props { 22 | pub cities: Cities, 23 | pub select_city: Callback, 24 | } 25 | 26 | impl Control { 27 | fn button(&self, ctx: &Context, city: City) -> Html { 28 | let name = city.name.clone(); 29 | let cb = ctx.link().callback(move |_| Msg::CityChosen(city.clone())); 30 | html! { 31 | 32 | } 33 | } 34 | } 35 | 36 | impl Component for Control { 37 | type Message = Msg; 38 | type Properties = Props; 39 | 40 | fn create(ctx: &Context) -> Self { 41 | Control { 42 | cities: ctx.props().cities.list.clone(), 43 | } 44 | } 45 | 46 | fn update(&mut self, ctx: &Context, msg: Self::Message) -> bool { 47 | match msg { 48 | Msg::CityChosen(city) => { 49 | log!(format!("Update: {:?}", city.name)); 50 | ctx.props().select_city.emit(city); 51 | } 52 | } 53 | true 54 | } 55 | 56 | fn view(&self, ctx: &Context) -> Html { 57 | html! { 58 |
59 |

{"Choose a city"}

60 |
61 | {for self.cities.iter().map(|city| Self::button(self, ctx, city.clone()))} 62 |
63 | 64 |
65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/yew-component/src/components/map_component.rs: -------------------------------------------------------------------------------- 1 | use gloo_utils::document; 2 | use leaflet::{LatLng, Map, MapOptions, TileLayer}; 3 | use wasm_bindgen::JsCast; 4 | use web_sys::{Element, HtmlElement, Node}; 5 | use yew::{html::ImplicitClone, prelude::*}; 6 | 7 | pub enum Msg {} 8 | 9 | pub struct MapComponent { 10 | map: Map, 11 | lat: Point, 12 | container: HtmlElement, 13 | } 14 | 15 | #[derive(Copy, Clone, Debug, PartialEq)] 16 | pub struct Point(pub f64, pub f64); 17 | 18 | #[derive(PartialEq, Clone, Debug)] 19 | pub struct City { 20 | pub name: String, 21 | pub lat: Point, 22 | } 23 | 24 | impl ImplicitClone for City {} 25 | 26 | #[derive(PartialEq, Properties, Clone)] 27 | pub struct Props { 28 | pub city: City, 29 | } 30 | 31 | impl MapComponent { 32 | fn render_map(&self) -> Html { 33 | let node: &Node = &self.container.clone().into(); 34 | Html::VRef(node.clone()) 35 | } 36 | } 37 | 38 | impl Component for MapComponent { 39 | type Message = Msg; 40 | type Properties = Props; 41 | 42 | fn create(ctx: &Context) -> Self { 43 | let props = ctx.props(); 44 | 45 | let container: Element = document().create_element("div").unwrap(); 46 | let container: HtmlElement = container.dyn_into().unwrap(); 47 | container.set_class_name("map"); 48 | let leaflet_map = Map::new_with_element(&container, &MapOptions::default()); 49 | Self { 50 | map: leaflet_map, 51 | container, 52 | lat: props.city.lat, 53 | } 54 | } 55 | 56 | fn rendered(&mut self, _ctx: &Context, first_render: bool) { 57 | if first_render { 58 | self.map 59 | .set_view(&LatLng::new(self.lat.0, self.lat.1), 11.0); 60 | add_tile_layer(&self.map); 61 | } 62 | } 63 | 64 | fn update(&mut self, _ctx: &Context, _msg: Self::Message) -> bool { 65 | false 66 | } 67 | 68 | fn changed(&mut self, ctx: &Context, _old_props: &Self::Properties) -> bool { 69 | let props = ctx.props(); 70 | 71 | if self.lat == props.city.lat { 72 | false 73 | } else { 74 | self.lat = props.city.lat; 75 | self.map 76 | .set_view(&LatLng::new(self.lat.0, self.lat.1), 11.0); 77 | true 78 | } 79 | } 80 | 81 | fn view(&self, _ctx: &Context) -> Html { 82 | html! { 83 |
84 | {self.render_map()} 85 |
86 | } 87 | } 88 | } 89 | 90 | fn add_tile_layer(map: &Map) { 91 | TileLayer::new("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").add_to(map); 92 | } 93 | -------------------------------------------------------------------------------- /examples/yew-component/src/main.rs: -------------------------------------------------------------------------------- 1 | use crate::components::{ 2 | control::{Cities, Control}, 3 | map_component::{City, MapComponent, Point}, 4 | }; 5 | use yew::prelude::*; 6 | mod components; 7 | 8 | enum Msg { 9 | SelectCity(City), 10 | } 11 | 12 | struct Model { 13 | city: City, 14 | cities: Cities, 15 | } 16 | 17 | impl Component for Model { 18 | type Message = Msg; 19 | type Properties = (); 20 | 21 | fn create(_ctx: &Context) -> Self { 22 | let aachen = City { 23 | name: "Aachen".to_string(), 24 | lat: Point(50.7597f64, 6.0967f64), 25 | }; 26 | let stuttgart = City { 27 | name: "Stuttgart".to_string(), 28 | lat: Point(48.7784f64, 9.1742f64), 29 | }; 30 | let cities: Cities = Cities { 31 | list: vec![aachen, stuttgart], 32 | }; 33 | let city = cities.list[0].clone(); 34 | Self { city, cities } 35 | } 36 | 37 | fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool { 38 | match msg { 39 | Msg::SelectCity(city) => { 40 | self.city = self 41 | .cities 42 | .list 43 | .iter() 44 | .find(|c| c.name == city.name) 45 | .unwrap() 46 | .clone(); 47 | } 48 | } 49 | true 50 | } 51 | 52 | fn view(&self, ctx: &Context) -> Html { 53 | let cb = ctx.link().callback(Msg::SelectCity); 54 | html! { 55 | <> 56 | 57 | 58 | 59 | } 60 | } 61 | } 62 | 63 | fn main() { 64 | yew::Renderer::::new().render(); 65 | } 66 | -------------------------------------------------------------------------------- /src/control.rs: -------------------------------------------------------------------------------- 1 | mod zoom; 2 | 3 | use crate::{create_object_with_properties, Map}; 4 | use js_sys::Object; 5 | use wasm_bindgen::prelude::*; 6 | use web_sys::HtmlElement; 7 | 8 | pub use zoom::{Zoom, ZoomOptions}; 9 | 10 | #[wasm_bindgen] 11 | extern "C" { 12 | #[derive(Clone, Debug)] 13 | #[wasm_bindgen(js_namespace = L, js_name = Control)] 14 | pub type Control; 15 | 16 | #[wasm_bindgen(js_namespace = ["L"], js_name = "control")] 17 | fn constructor_control(options: &ControlOptions) -> Control; 18 | 19 | #[wasm_bindgen(method, js_name = "getPosition")] 20 | pub fn get_position(this: &Control) -> String; 21 | 22 | #[wasm_bindgen(method, js_name = "setPosition")] 23 | pub fn set_position(this: &Control, position: &str) -> Control; 24 | 25 | #[wasm_bindgen(method, js_name = "getContainer")] 26 | pub fn get_container(this: &Control) -> HtmlElement; 27 | 28 | #[wasm_bindgen(method, js_name = "addTo")] 29 | pub fn add_to(this: &Control, map: &Map) -> Control; 30 | 31 | #[wasm_bindgen(method)] 32 | pub fn remove(this: &Control) -> Control; 33 | } 34 | 35 | create_object_with_properties!( 36 | (ControlOptions, ControlOptions), 37 | (position, position, String) 38 | ); 39 | 40 | impl Default for ControlOptions { 41 | fn default() -> Self { 42 | ControlOptions::new() 43 | } 44 | } 45 | 46 | impl Control { 47 | /// Creates a new [Control] instance. 48 | #[must_use] 49 | pub fn new(options: &ControlOptions) -> Self { 50 | constructor_control(options) 51 | } 52 | 53 | /// The given closure is executed when the control 54 | /// is added to a map using [addTo](Control::addTo). 55 | #[allow(clippy::missing_panics_doc)] 56 | pub fn on_add HtmlElement + 'static>(&self, on_add: C) { 57 | let closure = Closure::wrap(Box::new(on_add) as Box HtmlElement>); 58 | js_sys::Reflect::set(self, &JsValue::from("onAdd"), closure.as_ref()) 59 | .expect("Unable to set Control::onAdd()"); 60 | closure.forget(); 61 | } 62 | 63 | /// The given closure is executed when the control 64 | /// is removed from a map using [onRemove](Control::onRemove). 65 | #[allow(clippy::missing_panics_doc)] 66 | pub fn on_remove(&self, on_remove: C) { 67 | let closure = Closure::wrap(Box::new(on_remove) as Box); 68 | js_sys::Reflect::set(self, &JsValue::from("onRemove"), closure.as_ref()) 69 | .expect("Unable to set Control::onRemove()"); 70 | closure.forget(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/control/zoom.rs: -------------------------------------------------------------------------------- 1 | use super::Control; 2 | use crate::{object_constructor, object_property_set}; 3 | use js_sys::Object; 4 | use wasm_bindgen::prelude::*; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | #[derive(Clone, Debug)] 9 | #[wasm_bindgen(extends = Control, js_namespace = ["L", "Control"])] 10 | pub type Zoom; 11 | 12 | #[wasm_bindgen(js_namespace = ["L", "control"], js_name = "zoom")] 13 | fn constructor_zoom(options: &ZoomOptions) -> Zoom; 14 | 15 | #[wasm_bindgen(extends = Object , js_name = ZoomOptions)] 16 | #[derive(Debug, Clone, PartialEq, Eq)] 17 | #[wasm_bindgen(extends = Control)] 18 | pub type ZoomOptions; 19 | } 20 | 21 | impl Zoom { 22 | /// Creates a new `Zoom` control. 23 | #[must_use] 24 | pub fn new(options: &ZoomOptions) -> Self { 25 | constructor_zoom(options) 26 | } 27 | } 28 | 29 | impl ZoomOptions { 30 | object_constructor!(); 31 | 32 | // ZoomOptions 33 | object_property_set!(zoom_in_text, zoomInText, &str); 34 | object_property_set!(zoom_in_title, zoomInTitle, &str); 35 | object_property_set!(zoom_out_text, zoomOutText, &str); 36 | object_property_set!(zoom_out_title, zoomOutTitle, &str); 37 | 38 | // ControlOptions 39 | object_property_set!(position, position, &str); 40 | } 41 | 42 | impl Default for ZoomOptions { 43 | fn default() -> Self { 44 | ZoomOptions::new() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/crs.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | use crate::{LatLng, Point}; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | // CRS 8 | #[derive(Debug)] 9 | pub type Crs; 10 | 11 | #[wasm_bindgen(constructor, js_namespace = ["L", "CRS"], js_name = "Simple")] 12 | pub fn new_simple() -> Crs; 13 | 14 | #[wasm_bindgen(constructor, js_namespace = ["L", "CRS"], js_name = "Earth")] 15 | pub fn new_earth() -> Crs; 16 | 17 | #[wasm_bindgen(constructor, js_namespace = ["L", "CRS"], js_name = "EPSG3395")] 18 | pub fn new_epsg_3395() -> Crs; 19 | 20 | #[wasm_bindgen(constructor, js_namespace = ["L", "CRS"], js_name = "EPSG3857")] 21 | pub fn new_epsg_3857() -> Crs; 22 | 23 | #[wasm_bindgen(constructor, js_namespace = ["L", "CRS"], js_name = "EPSG4326")] 24 | pub fn new_epsg_4326() -> Crs; 25 | 26 | #[wasm_bindgen(constructor, js_namespace = ["L", "CRS"], js_name = "Base")] 27 | pub fn new_base() -> Crs; 28 | 29 | #[wasm_bindgen(method, js_name = "latLngToPoint")] 30 | pub fn lat_lng_to_point(this: &Crs, latlng: LatLng, zoom: f32) -> Point; 31 | } 32 | -------------------------------------------------------------------------------- /src/div_icon.rs: -------------------------------------------------------------------------------- 1 | use crate::{create_object_with_properties, Icon, Point}; 2 | use js_sys::Object; 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | #[derive(Debug, Clone)] 8 | #[wasm_bindgen(extends = Icon, js_namespace = L, js_name = Icon)] 9 | pub type DivIcon; 10 | 11 | #[wasm_bindgen(constructor, js_namespace = L)] 12 | pub fn new(options: &DivIconOptions) -> DivIcon; 13 | } 14 | 15 | create_object_with_properties!( 16 | (DivIconOptions, DivIconOptions), 17 | (html, html, String), 18 | (bg_pos, bgPos, Point), 19 | (icon_size, iconSize, Point), 20 | (icon_anchor, iconAnchor, Point), 21 | (popup_anchor, popupAnchor, Point), 22 | (tooltip_anchor, tooltipAnchor, Point), 23 | (class_name, className, String), 24 | (cross_origin, crossOrigin, String) 25 | ); 26 | 27 | impl Default for DivIconOptions { 28 | fn default() -> Self { 29 | Self::new() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/div_overlay.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | use web_sys::HtmlElement; 3 | 4 | use crate::{LatLng, Layer, Map}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | #[wasm_bindgen(js_namespace = L, js_name = DivOverlay, extends = Layer)] 9 | #[derive(Debug, Clone)] 10 | pub type DivOverlay; 11 | 12 | #[wasm_bindgen(constructor)] 13 | pub fn new(options: &JsValue) -> DivOverlay; 14 | 15 | #[wasm_bindgen(method, js_name = "setContent")] 16 | pub fn set_content(this: &DivOverlay, content: &JsValue) -> DivOverlay; 17 | 18 | #[wasm_bindgen(method, js_name = "getContent")] 19 | pub fn get_content(this: &DivOverlay) -> JsValue; 20 | 21 | #[wasm_bindgen(method, js_name = "setLatLng")] 22 | pub fn set_lat_lng(this: &DivOverlay, latlng: &JsValue) -> DivOverlay; 23 | 24 | #[wasm_bindgen(method, js_name = "getLatLng")] 25 | pub fn get_lat_lng(this: &DivOverlay) -> LatLng; 26 | 27 | #[wasm_bindgen(method)] 28 | pub fn toggle(this: &DivOverlay) -> DivOverlay; 29 | 30 | #[wasm_bindgen(method)] 31 | pub fn close(this: &DivOverlay) -> DivOverlay; 32 | 33 | #[wasm_bindgen(method, js_name = "isOpen")] 34 | pub fn is_open(this: &DivOverlay) -> bool; 35 | 36 | #[wasm_bindgen(method, js_name = "getElement")] 37 | pub fn get_element(this: &DivOverlay) -> HtmlElement; 38 | 39 | #[wasm_bindgen(method)] 40 | pub fn update(this: &DivOverlay); 41 | 42 | #[wasm_bindgen(method, js_name = "bringToFront")] 43 | pub fn bring_to_front(this: &DivOverlay) -> DivOverlay; 44 | 45 | #[wasm_bindgen(method, js_name = "bringToBack")] 46 | pub fn bring_to_back(this: &DivOverlay) -> DivOverlay; 47 | 48 | #[wasm_bindgen(method, js_name = "openOn")] 49 | pub fn open_on(this: &DivOverlay, map: &Map); 50 | } 51 | -------------------------------------------------------------------------------- /src/event.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen] 5 | extern "C" { 6 | #[wasm_bindgen(extends = Object, js_name = Event)] 7 | #[derive(Debug, Clone, Eq, PartialEq)] 8 | pub type Event; 9 | 10 | #[wasm_bindgen(constructor)] 11 | pub fn new() -> Event; 12 | 13 | #[wasm_bindgen(method, getter, js_name = "type")] 14 | pub fn event_type(this: &Event) -> String; 15 | 16 | #[wasm_bindgen(method, setter, js_name = "type")] 17 | pub fn set_event_type(this: &Event, value: &str); 18 | 19 | #[wasm_bindgen(method, getter, js_name = target)] 20 | pub fn target(this: &Event) -> Object; 21 | 22 | #[wasm_bindgen(method, setter, js_name = target)] 23 | pub fn set_target(this: &Event, value: &Object); 24 | 25 | #[wasm_bindgen(method, getter, js_name = sourceTarget)] 26 | pub fn source_target(this: &Event) -> Object; 27 | 28 | #[wasm_bindgen(method, setter, js_name = sourceTarget)] 29 | pub fn set_source_target(this: &Event, value: &Object); 30 | 31 | #[wasm_bindgen(method, getter, js_name = propagatedFrom)] 32 | pub fn propagated_from(this: &Event) -> Object; 33 | 34 | #[wasm_bindgen(method, setter, js_name = propagatedFrom)] 35 | pub fn set_propagated_from(this: &Event, value: &Object); 36 | 37 | #[wasm_bindgen(method, getter, js_name = layer)] 38 | pub fn layer(this: &Event) -> Object; 39 | 40 | #[wasm_bindgen(method, setter, js_name = layer)] 41 | pub fn set_layer(this: &Event, value: &Object); 42 | } 43 | -------------------------------------------------------------------------------- /src/evented.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | 3 | use crate::map::{DragEndEvent, TooltipEvent}; 4 | use crate::{ 5 | Circle, CircleMarker, Event, Layer, Map, Marker, MouseEvent, Path, Polygon, Polyline, 6 | PopupEvent, 7 | }; 8 | use js_sys::Object; 9 | use wasm_bindgen::convert::FromWasmAbi; 10 | use wasm_bindgen::prelude::*; 11 | 12 | #[wasm_bindgen] 13 | extern "C" { 14 | #[derive(Debug, Clone, PartialEq)] 15 | pub type Evented; 16 | 17 | /// Creates a new Evented object. 18 | /// 19 | /// [`on`](https://leafletjs.com/reference.html#evented-on) 20 | #[wasm_bindgen(method, js_name = on)] 21 | pub fn on(this: &Evented, kind: &str, handler: &JsValue) -> Evented; 22 | 23 | /// Removes an event listener. 24 | /// 25 | /// [`off`](https://leafletjs.com/reference.html#evented-off) 26 | #[wasm_bindgen(method)] 27 | pub fn off(this: &Evented, kind: &str, handler: &JsValue) -> Evented; 28 | 29 | #[wasm_bindgen(method, js_name = off)] 30 | pub fn off_by_name(this: &Evented, kind: &str) -> Evented; 31 | 32 | /// Removes all event listeners. 33 | /// 34 | /// [`off`](https://leafletjs.com/reference.html#evented-off) 35 | #[wasm_bindgen(method, js_name = off)] 36 | pub fn off_all(this: &Evented) -> Evented; 37 | 38 | /// Emits an event. 39 | /// 40 | /// [`fire`](https://leafletjs.com/reference.html#evented-fire) 41 | #[wasm_bindgen(method)] 42 | pub fn fire(this: &Evented, kind: &str, data: &Object, propagate: Option) -> Evented; 43 | 44 | /// Returns true if the event has listeners. 45 | /// 46 | /// [`listens`](https://leafletjs.com/reference.html#evented-listens) 47 | #[wasm_bindgen(method)] 48 | pub fn listens(this: &Evented, kind: &str, propagate: Option) -> bool; 49 | 50 | /// Returns true if the event has listeners. 51 | /// 52 | /// [`once`](https://leafletjs.com/reference.html#evented-once) 53 | #[wasm_bindgen(method)] 54 | pub fn once(this: &Evented, kind: &str, handler: &JsValue) -> Evented; 55 | 56 | /// Returns true if the event has listeners. 57 | /// 58 | /// [`addEventParent`](https://leafletjs.com/reference.html#evented-addeventparent) 59 | #[wasm_bindgen(method, js_name = "addEventParent")] 60 | pub fn add_event_parent(this: &Evented, other: &Evented) -> Evented; 61 | 62 | /// Returns true if the event has listeners. 63 | /// 64 | /// ['removeEventParent'](https://leafletjs.com/reference.html#evented-removeeventparent) 65 | #[wasm_bindgen(method, js_name = "removeEventParent")] 66 | pub fn remove_event_parent(this: &Evented, other: &Evented) -> Evented; 67 | 68 | /// Returns true if the event has listeners. 69 | /// 70 | /// [`addEventListener`](https://leafletjs.com/reference.html#evented-addeventlistener) 71 | #[wasm_bindgen(method, js_name = "addEventListener")] 72 | pub fn add_event_listener( 73 | this: &Evented, 74 | kind: &str, 75 | handler: &Closure, 76 | ) -> Evented; 77 | 78 | /// Returns true if the event has listeners. 79 | /// 80 | /// [`removeEventListener`](https://leafletjs.com/reference.html#evented-removeeventlistener) 81 | #[wasm_bindgen(method, js_name = "removeEventListener")] 82 | pub fn remove_event_listener( 83 | this: &Evented, 84 | kind: &str, 85 | handler: &Closure, 86 | ) -> Evented; 87 | 88 | /// Clears all event listeners. 89 | /// 90 | /// [`clearAllEventListeners`](https://leafletjs.com/reference.html#evented-cleareventlisteners) 91 | #[wasm_bindgen(method, js_name = "clearAllEventListeners")] 92 | pub fn clear_all_event_listeners(this: &Evented) -> Evented; 93 | 94 | /// Adds a one time event listener. 95 | /// 96 | /// [`addOneTimeEventListener`](https://leafletjs.com/reference.html#evented-addonetimeeventlistener) 97 | #[wasm_bindgen(method, js_name = "addOneTimeEventListener")] 98 | pub fn add_one_time_event_listener( 99 | this: &Evented, 100 | kind: &str, 101 | handler: &Closure, 102 | ) -> Evented; 103 | 104 | /// Fires an event. 105 | /// 106 | /// [`fireEvent`](https://leafletjs.com/reference.html#evented-fireevent) 107 | #[wasm_bindgen(method, js_name = "fireEvent")] 108 | pub fn fire_event( 109 | this: &Evented, 110 | kind: &str, 111 | data: &Object, 112 | propagate: Option, 113 | ) -> Evented; 114 | 115 | /// Returns true if the event has listeners. 116 | /// 117 | /// [`hasEventListeners`](https://leafletjs.com/reference.html#evented-haseventlisteners) 118 | #[wasm_bindgen(method, js_name = "hasEventListeners")] 119 | pub fn has_event_listeners(this: &Evented, kind: &str, propagate: Option) -> bool; 120 | } 121 | 122 | pub trait FromLeafletEvent: FromWasmAbi { 123 | type EventType; 124 | fn from_leaflet_event(event: Self::EventType) -> Self; 125 | } 126 | 127 | impl FromLeafletEvent for Event { 128 | type EventType = Event; 129 | fn from_leaflet_event(event: Self::EventType) -> Self { 130 | event 131 | } 132 | } 133 | 134 | impl FromLeafletEvent for MouseEvent { 135 | type EventType = Event; 136 | fn from_leaflet_event(event: Self::EventType) -> Self { 137 | event.unchecked_into() 138 | } 139 | } 140 | 141 | impl FromLeafletEvent for DragEndEvent { 142 | type EventType = Event; 143 | fn from_leaflet_event(event: Self::EventType) -> Self { 144 | event.unchecked_into() 145 | } 146 | } 147 | 148 | impl FromLeafletEvent for TooltipEvent { 149 | type EventType = Event; 150 | fn from_leaflet_event(event: Self::EventType) -> Self { 151 | event.unchecked_into() 152 | } 153 | } 154 | 155 | pub struct EventedHandle { 156 | target: Evented, 157 | event_type: Cow<'static, str>, 158 | callback: Closure, 159 | } 160 | 161 | impl EventedHandle { 162 | #[must_use] 163 | pub fn callback(&self) -> &Closure { 164 | &self.callback 165 | } 166 | } 167 | 168 | impl Drop for EventedHandle { 169 | fn drop(&mut self) { 170 | self.target 171 | .off(&self.event_type, self.callback.as_ref().unchecked_ref()); 172 | } 173 | } 174 | 175 | impl Evented { 176 | pub fn on_leaflet_event(target: &T, event: S, callback: F) -> EventedHandle 177 | where 178 | T: EventedTarget, 179 | E: FromLeafletEvent + 'static, 180 | F: FnMut(E) + 'static, 181 | S: Into>, 182 | { 183 | let callback = Closure::wrap(Box::new(callback) as Box); 184 | let event_type = event.into(); 185 | let target = target.as_evented(); 186 | target.on(&event_type, callback.as_ref().unchecked_ref()); 187 | EventedHandle { 188 | target, 189 | event_type, 190 | callback, 191 | } 192 | } 193 | } 194 | 195 | pub trait EventedTarget { 196 | fn as_evented(&self) -> Evented; 197 | } 198 | 199 | impl EventedTarget for Layer { 200 | fn as_evented(&self) -> Evented { 201 | self.unchecked_ref::().clone() 202 | } 203 | } 204 | 205 | impl EventedTarget for &Layer { 206 | fn as_evented(&self) -> Evented { 207 | self.unchecked_ref::().clone() 208 | } 209 | } 210 | 211 | impl EventedTarget for &Evented { 212 | fn as_evented(&self) -> Evented { 213 | self.unchecked_ref::().clone() 214 | } 215 | } 216 | 217 | impl EventedTarget for &Map { 218 | fn as_evented(&self) -> Evented { 219 | self.unchecked_ref::().clone() 220 | } 221 | } 222 | 223 | impl EventedTarget for Marker { 224 | fn as_evented(&self) -> Evented { 225 | self.unchecked_ref::().clone() 226 | } 227 | } 228 | 229 | impl EventedTarget for &Marker { 230 | fn as_evented(&self) -> Evented { 231 | self.unchecked_ref::().clone() 232 | } 233 | } 234 | 235 | impl EventedTarget for &Path { 236 | fn as_evented(&self) -> Evented { 237 | self.unchecked_ref::().clone() 238 | } 239 | } 240 | 241 | impl EventedTarget for &Polygon { 242 | fn as_evented(&self) -> Evented { 243 | self.unchecked_ref::().clone() 244 | } 245 | } 246 | 247 | impl EventedTarget for &Polyline { 248 | fn as_evented(&self) -> Evented { 249 | self.unchecked_ref::().clone() 250 | } 251 | } 252 | 253 | impl EventedTarget for &Circle { 254 | fn as_evented(&self) -> Evented { 255 | self.unchecked_ref::().clone() 256 | } 257 | } 258 | 259 | impl EventedTarget for &CircleMarker { 260 | fn as_evented(&self) -> Evented { 261 | self.unchecked_ref::().clone() 262 | } 263 | } 264 | 265 | pub trait LeafletEventHandler { 266 | fn on(&self, event: &str, callback: &JsValue); 267 | } 268 | 269 | pub trait MoveEvents 270 | where 271 | Self: LeafletEventHandler, 272 | { 273 | fn on_move(&self, callback: Box) { 274 | let closure = Closure::wrap(callback); 275 | self.on("move", &closure.into_js_value()); 276 | } 277 | } 278 | 279 | pub trait MouseEvents 280 | where 281 | Self: LeafletEventHandler, 282 | { 283 | fn on_click(&self, callback: Box) { 284 | let closure = Closure::wrap(callback); 285 | self.on("click", &closure.into_js_value()); 286 | } 287 | 288 | fn on_double_click(&self, callback: Box) { 289 | let closure = Closure::wrap(callback); 290 | self.on("dblclick", &closure.into_js_value()); 291 | } 292 | 293 | fn on_mouse_down(&self, callback: Box) { 294 | let closure = Closure::wrap(callback); 295 | self.on("mousedown", &closure.into_js_value()); 296 | } 297 | 298 | fn on_mouse_up(&self, callback: Box) { 299 | let closure = Closure::wrap(callback); 300 | self.on("mouseup", &closure.into_js_value()); 301 | } 302 | 303 | fn on_mouse_over(&self, callback: Box) { 304 | let closure = Closure::wrap(callback); 305 | self.on("mouseover", &closure.into_js_value()); 306 | } 307 | 308 | fn on_mouse_out(&self, callback: Box) { 309 | let closure = Closure::wrap(callback); 310 | self.on("mouseout", &closure.into_js_value()); 311 | } 312 | 313 | fn on_context_menu(&self, callback: Box) { 314 | let closure = Closure::wrap(callback); 315 | self.on("contextmenu", &closure.into_js_value()); 316 | } 317 | } 318 | 319 | pub trait DragEvents 320 | where 321 | Self: LeafletEventHandler, 322 | { 323 | fn on_drag_start(&self, callback: Box) { 324 | let closure = Closure::wrap(callback); 325 | self.on("dragstart", &closure.into_js_value()); 326 | } 327 | 328 | fn on_move_start(&self, callback: Box) { 329 | let closure = Closure::wrap(callback); 330 | self.on("movestart", &closure.into_js_value()); 331 | } 332 | 333 | fn on_drag(&self, callback: Box) { 334 | let closure = Closure::wrap(callback); 335 | self.on("drag", &closure.into_js_value()); 336 | } 337 | 338 | fn on_drag_end(&self, callback: Box) { 339 | let closure = Closure::wrap(callback); 340 | self.on("dragend", &closure.into_js_value()); 341 | } 342 | 343 | fn on_move_end(&self, callback: Box) { 344 | let closure = Closure::wrap(callback); 345 | self.on("moveend", &closure.into_js_value()); 346 | } 347 | } 348 | 349 | pub trait LayerEvents 350 | where 351 | Self: LeafletEventHandler, 352 | { 353 | fn on_add(&self, callback: Box) { 354 | let closure = Closure::wrap(callback); 355 | self.on("add", &closure.into_js_value()); 356 | } 357 | 358 | fn on_remove(&self, callback: Box) { 359 | let closure = Closure::wrap(callback); 360 | self.on("remove", &closure.into_js_value()); 361 | } 362 | } 363 | 364 | pub trait PopupEvents 365 | where 366 | Self: LeafletEventHandler, 367 | { 368 | fn on_popup_open(&self, callback: Box) { 369 | let closure = Closure::wrap(callback); 370 | self.on("popupopen", &closure.into_js_value()); 371 | } 372 | 373 | fn on_popup_close(&self, callback: Box) { 374 | let closure = Closure::wrap(callback); 375 | self.on("popupclose", &closure.into_js_value()); 376 | } 377 | } 378 | 379 | pub trait TooltipEvents 380 | where 381 | Self: LeafletEventHandler, 382 | { 383 | fn on_tooltip_open(&self, callback: Box) { 384 | let closure = Closure::wrap(callback); 385 | self.on("tooltipopen", &closure.into_js_value()); 386 | } 387 | 388 | fn on_tooltip_close(&self, callback: Box) { 389 | let closure = Closure::wrap(callback); 390 | self.on("tooltipclose", &closure.into_js_value()); 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /src/feature_group.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | use crate::{LatLngBounds, LayerGroup}; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | /// [`FeatureGroup`](https://leafletjs.com/reference-1.7.1.html#featuregroup) 8 | #[derive(Clone, Debug)] 9 | #[wasm_bindgen(extends = LayerGroup)] 10 | pub type FeatureGroup; 11 | 12 | #[wasm_bindgen(constructor, js_namespace = L)] 13 | pub fn new() -> FeatureGroup; 14 | 15 | /// [`setStyle`](https://leafletjs.com/reference-1.7.1.html#featuregroup-setstyle) 16 | #[wasm_bindgen(method, js_name = "setStyle")] 17 | pub fn set_style(this: &FeatureGroup, style: &JsValue); 18 | 19 | /// [`bringToFront`](https://leafletjs.com/reference-1.7.1.html#featuregroup-bringtofront) 20 | #[wasm_bindgen(method, js_name = "bringToFront")] 21 | pub fn bring_to_front(this: &FeatureGroup); 22 | 23 | /// [`bringToBack`](https://leafletjs.com/reference-1.7.1.html#featuregroup-bringtoback) 24 | #[wasm_bindgen(method, js_name = "bringToBack")] 25 | pub fn bring_to_back(this: &FeatureGroup); 26 | 27 | /// [`getBounds`](https://leafletjs.com/reference-1.7.1.html#featuregroup-getbounds) 28 | #[wasm_bindgen(method, js_name = "getBounds")] 29 | pub fn get_bounds(this: &FeatureGroup) -> LatLngBounds; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/geo_json.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | use crate::Layer; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | /// [`GeoJSON`](https://leafletjs.com/reference-1.7.1.html#geojson) 8 | #[derive(Clone, Debug)] 9 | #[wasm_bindgen(extends = Layer, js_name = "geoJSON")] 10 | pub type GeoJson; 11 | 12 | /// [`L.geoJSON`](https://leafletjs.com/reference-1.7.1.html#geojson-l-geojson) 13 | #[wasm_bindgen(js_namespace = L, js_name = "geoJSON")] 14 | pub fn geo_json(geojson: &JsValue, options: &JsValue) -> GeoJson; 15 | 16 | /// [`addData`](https://leafletjs.com/reference-1.7.1.html#geojson-adddata) 17 | #[wasm_bindgen(method, js_name = "addData")] 18 | pub fn add_data(this: &GeoJson, data: &JsValue); 19 | 20 | /// [`resetStyle`](https://leafletjs.com/reference-1.7.1.html#geojson-resetstyle) 21 | #[wasm_bindgen(method, js_name = "resetStyle")] 22 | pub fn reset_style(this: &GeoJson, layer: Option<&Layer>); 23 | 24 | /// [`setStyle`](https://leafletjs.com/reference-1.7.1.html#geojson-setstyle) 25 | #[wasm_bindgen(method, js_name = "setStyle")] 26 | pub fn set_style(this: &GeoJson, style: &JsValue); 27 | } 28 | -------------------------------------------------------------------------------- /src/grid_layer.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | use web_sys::HtmlElement; 4 | 5 | use crate::{create_object_with_properties, LatLngBounds, Layer, LayerOptions, Point}; 6 | 7 | #[wasm_bindgen] 8 | extern "C" { 9 | 10 | #[wasm_bindgen(extends = Layer)] 11 | #[derive(Debug, Clone, PartialEq)] 12 | pub type GridLayer; 13 | 14 | #[wasm_bindgen(constructor, js_namespace = L)] 15 | pub fn new() -> GridLayer; 16 | 17 | #[wasm_bindgen(constructor, js_namespace = L)] 18 | pub fn new_with_options(options: &GridLayerOptions) -> GridLayer; 19 | 20 | #[wasm_bindgen(method, js_name = bringToFront)] 21 | pub fn bring_to_front(this: &GridLayer) -> GridLayer; 22 | 23 | #[wasm_bindgen(method, js_name = bringToBack)] 24 | pub fn bring_to_back(this: &GridLayer) -> GridLayer; 25 | 26 | #[wasm_bindgen(method, js_name = getContainer)] 27 | pub fn get_container(this: &GridLayer) -> HtmlElement; 28 | 29 | #[wasm_bindgen(method, js_name = setOpacity)] 30 | pub fn set_opacity(this: &GridLayer, opacity: f64) -> GridLayer; 31 | 32 | #[wasm_bindgen(method, js_name = setZIndex)] 33 | pub fn set_z_index(this: &GridLayer, opacity: f64) -> GridLayer; 34 | 35 | #[wasm_bindgen(method, js_name = isLoading)] 36 | pub fn is_loading(this: &GridLayer) -> bool; 37 | 38 | #[wasm_bindgen(method, js_name = redraw)] 39 | pub fn redraw(this: &GridLayer) -> GridLayer; 40 | } 41 | 42 | create_object_with_properties!( 43 | (GridLayerOptions, GridLayerOptions, LayerOptions), 44 | (tile_size, tileSize, f64), 45 | (tile_size_point, tileSize, Point), 46 | (opacity, opacity, f64), 47 | (update_when_idle, updateWhenIdle, bool), 48 | (update_when_zooming, updateWhenZooming, bool), 49 | (update_interval, updateInterval, f64), 50 | (z_index, zIndex, f64), 51 | (bounds, bounds, LatLngBounds), 52 | (min_zoom, minZoom, f64), 53 | (max_zoom, maxZoom, f64), 54 | (min_native_zoom, minNativeZoom, f64), 55 | (max_native_zoom, maxNativeZoom, f64), 56 | (no_wrap, noWrap, bool), 57 | (pane, pane, String), 58 | (class_name, className, String), 59 | (keep_buffer, keepBuffer, f64) 60 | ); 61 | 62 | impl Default for GridLayerOptions { 63 | fn default() -> Self { 64 | GridLayerOptions::new() 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/handler.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen] 5 | extern "C" { 6 | #[wasm_bindgen(extends = Object, js_name = DivOverlay)] 7 | #[derive(Debug, Clone)] 8 | pub type Handler; 9 | 10 | /// Create a new handler 11 | #[wasm_bindgen(method)] 12 | pub fn enable(this: &Handler) -> Handler; 13 | 14 | /// Remove the handler 15 | #[wasm_bindgen(method)] 16 | pub fn disable(this: &Handler) -> Handler; 17 | 18 | /// Check if the handler is enabled 19 | #[wasm_bindgen(method)] 20 | pub fn enabled(this: &Handler) -> bool; 21 | } 22 | -------------------------------------------------------------------------------- /src/icon.rs: -------------------------------------------------------------------------------- 1 | use crate::{create_object_with_properties, Point}; 2 | use js_sys::Object; 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | #[derive(Debug, Clone)] 8 | #[wasm_bindgen(js_namespace = L, js_name = Icon)] 9 | pub type Icon; 10 | 11 | #[wasm_bindgen(constructor, js_namespace = L)] 12 | pub fn new(options: &IconOptions) -> Icon; 13 | } 14 | 15 | create_object_with_properties!( 16 | (IconOptions, IconOptions), 17 | (icon_url, iconUrl, String), 18 | (icon_size, iconSize, Point), 19 | (icon_anchor, iconAnchor, Point), 20 | (popup_anchor, popupAnchor, Point), 21 | (shadow_anchor, shadowAnchor, Point), 22 | (tooltip_anchor, tooltipAnchor, Point), 23 | (shadow_url, shadowUrl, String), 24 | (shadow_retina_url, shadowRetinaUrl, String), 25 | (shadow_size, shadowSize, Point), 26 | (class_name, className, String), 27 | (cross_origin, crossOrigin, String) 28 | ); 29 | 30 | impl Default for IconOptions { 31 | fn default() -> Self { 32 | Self::new() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/lat_lng.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) HeadlessStudio 2023. 3 | */ 4 | 5 | use std::ops::{Add, AddAssign, Div, Sub}; 6 | use wasm_bindgen::prelude::*; 7 | 8 | #[wasm_bindgen] 9 | extern "C" { 10 | #[derive(Debug, Default, Clone)] 11 | pub type LatLng; 12 | 13 | #[wasm_bindgen(constructor, js_namespace = L)] 14 | pub fn new(lat: f64, lng: f64) -> LatLng; 15 | 16 | #[wasm_bindgen(method, getter)] 17 | pub fn lat(this: &LatLng) -> f64; 18 | 19 | #[wasm_bindgen(method, getter)] 20 | pub fn lng(this: &LatLng) -> f64; 21 | 22 | #[wasm_bindgen(method, setter)] 23 | pub fn set_lat(this: &LatLng, value: f64) -> f64; 24 | 25 | #[wasm_bindgen(method, setter)] 26 | pub fn set_lng(this: &LatLng, value: f64) -> f64; 27 | 28 | #[wasm_bindgen(method, js_name = distanceTo)] 29 | pub fn distance_to(this: &LatLng, otherLatLng: &LatLng) -> f64; 30 | 31 | } 32 | 33 | #[allow(clippy::from_over_into)] 34 | impl Into for (f64, f64) { 35 | fn into(self) -> LatLng { 36 | LatLng::new(self.0, self.1) 37 | } 38 | } 39 | 40 | #[allow(clippy::from_over_into)] 41 | impl Into for [f64; 2] { 42 | fn into(self) -> LatLng { 43 | LatLng::new(self[0], self[1]) 44 | } 45 | } 46 | 47 | impl Add for LatLng { 48 | type Output = LatLng; 49 | 50 | fn add(self, rhs: LatLng) -> Self::Output { 51 | LatLng::new(self.lat() + rhs.lat(), self.lng() + rhs.lng()) 52 | } 53 | } 54 | 55 | impl Add for &LatLng { 56 | type Output = LatLng; 57 | 58 | fn add(self, rhs: LatLng) -> Self::Output { 59 | LatLng::new(self.lat() + rhs.lat(), self.lng() + rhs.lng()) 60 | } 61 | } 62 | 63 | impl Sub for LatLng { 64 | type Output = LatLng; 65 | 66 | fn sub(self, rhs: LatLng) -> Self::Output { 67 | LatLng::new(self.lat() - rhs.lat(), self.lng() - rhs.lng()) 68 | } 69 | } 70 | 71 | impl Sub<&LatLng> for LatLng { 72 | type Output = LatLng; 73 | 74 | fn sub(self, rhs: &LatLng) -> Self::Output { 75 | LatLng::new(self.lat() - rhs.lat(), self.lng() - rhs.lng()) 76 | } 77 | } 78 | 79 | impl Sub for &LatLng { 80 | type Output = LatLng; 81 | 82 | fn sub(self, rhs: LatLng) -> Self::Output { 83 | LatLng::new(self.lat() - rhs.lat(), self.lng() - rhs.lng()) 84 | } 85 | } 86 | 87 | impl AddAssign for LatLng { 88 | fn add_assign(&mut self, rhs: LatLng) { 89 | self.set_lat(self.lat() + rhs.lat()); 90 | self.set_lng(self.lng() + rhs.lng()); 91 | } 92 | } 93 | 94 | impl Div for LatLng { 95 | type Output = LatLng; 96 | 97 | fn div(self, rhs: f64) -> Self::Output { 98 | LatLng::new(self.lat() / rhs, self.lng() / rhs) 99 | } 100 | } 101 | 102 | impl Div for &LatLng { 103 | type Output = LatLng; 104 | 105 | fn div(self, rhs: f64) -> Self::Output { 106 | LatLng::new(self.lat() / rhs, self.lng() / rhs) 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/lat_lng_bounds.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | use crate::LatLng; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | #[derive(Debug)] 8 | pub type LatLngBounds; 9 | 10 | #[wasm_bindgen(constructor, js_namespace = L)] 11 | pub fn new(corner1: &LatLng, corner2: &LatLng) -> LatLngBounds; 12 | 13 | #[wasm_bindgen(method, js_name = getNorthEast)] 14 | pub fn get_north_east(this: &LatLngBounds) -> LatLng; 15 | 16 | #[wasm_bindgen(method, js_name = getSouthWest)] 17 | pub fn get_south_west(this: &LatLngBounds) -> LatLng; 18 | 19 | #[wasm_bindgen(method)] 20 | pub fn contains(this: &LatLngBounds, latlng: &LatLng) -> bool; 21 | 22 | #[wasm_bindgen(method, js_name = toBBoxString)] 23 | pub fn to_bbox_string(this: &LatLngBounds) -> String; 24 | } 25 | 26 | impl From<(LatLng, LatLng)> for LatLngBounds { 27 | fn from(value: (LatLng, LatLng)) -> LatLngBounds { 28 | LatLngBounds::new(&value.0, &value.1) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/layer.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | use web_sys::HtmlElement; 4 | 5 | use crate::evented::{LayerEvents, LeafletEventHandler, PopupEvents, TooltipEvents}; 6 | use crate::{create_object_with_properties, Evented, LatLng, LayerGroup, Map, Popup, Tooltip}; 7 | 8 | #[wasm_bindgen] 9 | extern "C" { 10 | #[wasm_bindgen(extends = Evented)] 11 | #[derive(Debug, Clone, PartialEq)] 12 | pub type Layer; 13 | 14 | /// [`addTo`](https://leafletjs.com/reference.html#layer-addto) 15 | #[wasm_bindgen(method, js_name = addTo)] 16 | pub fn add_to(this: &Layer, map: &Map) -> Layer; 17 | 18 | /// [`addTo`](https://leafletjs.com/reference.html#layer-addto) 19 | #[wasm_bindgen(method, js_name = addTo)] 20 | pub fn add_to_layer_group(this: &Layer, layerGroup: &LayerGroup) -> Layer; 21 | 22 | #[wasm_bindgen(method, js_name = remove)] 23 | pub fn remove(this: &Layer) -> Layer; 24 | 25 | #[wasm_bindgen(method, js_name = removeFrom)] 26 | pub fn remove_from(this: &Layer, map: &Map) -> Layer; 27 | 28 | #[wasm_bindgen(method, js_name = removeFrom)] 29 | pub fn remove_from_layer_group(this: &Layer, map: &LayerGroup) -> Layer; 30 | 31 | #[wasm_bindgen(method, js_name = getPane)] 32 | pub fn get_pane(this: &Layer) -> HtmlElement; 33 | 34 | #[wasm_bindgen(method, js_name = getAttribution)] 35 | pub fn get_attribution(this: &Layer) -> String; 36 | 37 | // Layer Popup Methods 38 | 39 | /// [`bindPopup`](https://leafletjs.com/reference.html#layer-bindpopup) 40 | #[wasm_bindgen(method, js_name = bindPopup)] 41 | pub fn bind_popup(this: &Layer, content: &Popup) -> Layer; 42 | 43 | /// [`bindPopup`](https://leafletjs.com/reference.html#layer-bindpopup) 44 | #[wasm_bindgen(method, js_name = bindPopup)] 45 | pub fn bind_popup_with_options(this: &Layer, content: &JsValue, options: &JsValue) -> Layer; 46 | 47 | /// [`unbindPopup`](https://leafletjs.com/reference.html#layer-unbindpopup) 48 | #[wasm_bindgen(method, js_name = unbindPopup)] 49 | pub fn unbind_popup(this: &Layer) -> Layer; 50 | 51 | /// [`openPopup`](https://leafletjs.com/reference.html#layer-openpopup) 52 | #[wasm_bindgen(method, js_name = openPopup)] 53 | pub fn open_popup(this: &Layer) -> Layer; 54 | 55 | /// [`openPopup`](https://leafletjs.com/reference.html#layer-openpopup) 56 | #[wasm_bindgen(method, js_name = openPopup)] 57 | pub fn open_popup_with_lat_lng(this: &Layer, lat_lng: &LatLng) -> Layer; 58 | 59 | /// [`closePopup`](https://leafletjs.com/reference.html#layer-closepopup) 60 | #[wasm_bindgen(method, js_name = closePopup)] 61 | pub fn close_popup(this: &Layer) -> Layer; 62 | 63 | /// [`togglePopup`](https://leafletjs.com/reference.html#layer-togglepopup) 64 | #[wasm_bindgen(method, js_name = togglePopup)] 65 | pub fn toggle_popup(this: &Layer) -> Layer; 66 | 67 | /// [`isPopupOpen`](https://leafletjs.com/reference.html#layer-ispopupopen) 68 | #[wasm_bindgen(method, js_name = isPopupOpen)] 69 | pub fn is_popup_open(this: &Layer) -> bool; 70 | 71 | /// [`setPopupContent`](https://leafletjs.com/reference.html#layer-setpopupcontent) 72 | #[wasm_bindgen(method, js_name = setPopupContent)] 73 | pub fn set_popup_content(this: &Layer, content: &JsValue) -> Layer; 74 | 75 | /// [`getPopup`](https://leafletjs.com/reference.html#layer-getpopup) 76 | #[wasm_bindgen(method, js_name = getPopup)] 77 | pub fn get_popup(this: &Layer) -> Popup; 78 | 79 | // Layer Tooltip Methods 80 | 81 | /// [`bindTooltip`](https://leafletjs.com/reference.html#layer-bindtooltip) 82 | #[wasm_bindgen(method, js_name = bindTooltip)] 83 | pub fn bind_tooltip(this: &Layer, tooltip: &Tooltip) -> Layer; 84 | 85 | #[wasm_bindgen(method, js_name = bindTooltipWithContent)] 86 | pub fn bind_tooltip_with_content(this: &Layer, content: &JsValue, options: &JsValue) -> Layer; 87 | 88 | /// [`unbindTooltip`](https://leafletjs.com/reference.html#layer-unbindtooltip) 89 | #[wasm_bindgen(method, js_name = unbindTooltip)] 90 | pub fn unbind_tooltip(this: &Layer) -> Layer; 91 | 92 | /// [`openTooltip`](https://leafletjs.com/reference.html#layer-opentooltip) 93 | #[wasm_bindgen(method, js_name = openTooltip)] 94 | pub fn open_tooltip(this: &Layer, lat_lng: &LatLng) -> Layer; 95 | 96 | /// [`closeTooltip`](https://leafletjs.com/reference.html#layer-closetooltip) 97 | #[wasm_bindgen(method, js_name = closeTooltip)] 98 | pub fn close_tooltip(this: &Layer) -> Layer; 99 | 100 | /// [`toggleTooltip`](https://leafletjs.com/reference.html#layer-toggletooltip) 101 | #[wasm_bindgen(method, js_name = toggleTooltip)] 102 | pub fn toggle_tooltip(this: &Layer) -> Layer; 103 | 104 | /// [`isTooltipOpen`](https://leafletjs.com/reference.html#layer-istooltipopen) 105 | #[wasm_bindgen(method, js_name = isTooltipOpen)] 106 | pub fn is_tooltip_open(this: &Layer) -> bool; 107 | 108 | /// [`setTooltipContent`](https://leafletjs.com/reference.html#layer-settooltipcontent) 109 | #[wasm_bindgen(method, js_name = setTooltipContent)] 110 | pub fn set_tooltip_content(this: &Layer, content: &JsValue) -> Layer; 111 | 112 | /// [`getTooltip`](https://leafletjs.com/reference.html#layer-gettooltip) 113 | #[wasm_bindgen(method, js_name = getTooltip)] 114 | pub fn get_tooltip(this: &Layer) -> Tooltip; 115 | } 116 | 117 | create_object_with_properties!( 118 | (LayerOptions, LayerOptions), 119 | (pane, pane, String), 120 | (attribution, attribution, String) 121 | ); 122 | 123 | impl LeafletEventHandler for Layer { 124 | fn on(&self, event: &str, callback: &JsValue) { 125 | self.unchecked_ref::().on(event, callback); 126 | } 127 | } 128 | 129 | impl LayerEvents for Layer {} 130 | impl PopupEvents for Layer {} 131 | impl TooltipEvents for Layer {} 132 | -------------------------------------------------------------------------------- /src/layer_control.rs: -------------------------------------------------------------------------------- 1 | use super::Control; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen] 5 | extern "C" { 6 | #[derive(Debug, Clone)] 7 | #[wasm_bindgen(js_namespace = ["L", "control"], js_name = Layers, extends = Control)] 8 | pub type LayerControl; 9 | 10 | #[wasm_bindgen(constructor)] 11 | pub fn new(base_layers: &JsValue) -> LayerControl; 12 | } 13 | -------------------------------------------------------------------------------- /src/layer_group.rs: -------------------------------------------------------------------------------- 1 | use js_sys::{Array, Object}; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::Layer; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | /// [`LayerGroup`](https://leafletjs.com/reference.html#layergroup) 9 | #[derive(Clone, Debug)] 10 | #[wasm_bindgen(extends = Layer)] 11 | pub type LayerGroup; 12 | 13 | #[wasm_bindgen(constructor, js_namespace = L)] 14 | pub fn new() -> LayerGroup; 15 | 16 | /// [`toGeoJSON`](https://leafletjs.com/reference.html#layergroup-togeojson) 17 | #[wasm_bindgen(method, js_name = toGeoJSON)] 18 | pub fn to_geo_json(this: &LayerGroup) -> JsValue; 19 | 20 | /// [`addLayer`](https://leafletjs.com/reference.html#layergroup-addlayer) 21 | #[wasm_bindgen(method, js_name = addLayer)] 22 | pub fn add_layer(this: &LayerGroup, layer: &Layer) -> LayerGroup; 23 | 24 | /// [`removeLayer`](https://leafletjs.com/reference.html#layergroup-removelayer) 25 | #[wasm_bindgen(method, js_name = removeLayer)] 26 | pub fn remove_layer(this: &LayerGroup, layer: &Layer) -> LayerGroup; 27 | 28 | /// [`hasLayer`](https://leafletjs.com/reference.html#layergroup-haslayer) 29 | #[wasm_bindgen(method, js_name = hasLayer)] 30 | pub fn has_layer(this: &LayerGroup, layer: &Layer) -> bool; 31 | 32 | /// [`clearLayers`](https://leafletjs.com/reference.html#layergroup-clearlayers) 33 | #[wasm_bindgen(method, js_name = clearLayers)] 34 | pub fn clear_layers(this: &LayerGroup) -> LayerGroup; 35 | 36 | #[wasm_bindgen(method)] 37 | pub fn invoke(this: &LayerGroup, method_name: &str) -> LayerGroup; 38 | 39 | #[wasm_bindgen(method, js_name = eachLayer)] 40 | pub fn each_layer(this: &LayerGroup, callback: &Closure) -> LayerGroup; 41 | 42 | #[wasm_bindgen(method, js_name = eachLayer)] 43 | pub fn each_layer_with_context( 44 | this: &LayerGroup, 45 | callback: &Closure, 46 | context: &Object, 47 | ) -> LayerGroup; 48 | 49 | #[wasm_bindgen(method, js_name = getLayer)] 50 | pub fn get_layer(this: &LayerGroup, id: i32) -> Layer; 51 | 52 | #[wasm_bindgen(method, js_name = getLayers)] 53 | pub fn get_layers(this: &LayerGroup) -> Array; 54 | 55 | #[wasm_bindgen(method, js_name = setZIndex)] 56 | pub fn set_z_index(this: &LayerGroup, index: f64) -> LayerGroup; 57 | 58 | #[wasm_bindgen(method, js_name = getLayerId)] 59 | pub fn get_layer_id(this: &LayerGroup, layer: &Layer) -> i32; 60 | } 61 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod control; 2 | mod crs; 3 | mod div_icon; 4 | mod div_overlay; 5 | mod event; 6 | mod evented; 7 | mod feature_group; 8 | mod geo_json; 9 | mod grid_layer; 10 | mod handler; 11 | mod icon; 12 | mod lat_lng; 13 | mod lat_lng_bounds; 14 | mod layer; 15 | mod layer_control; 16 | mod layer_group; 17 | mod map; 18 | mod marker; 19 | mod point; 20 | mod popup; 21 | mod raster; 22 | mod shapes; 23 | mod tooltip; 24 | mod util; 25 | 26 | use js_sys::Array; 27 | use paste::paste; 28 | 29 | pub use control::{Control, ControlOptions, Zoom, ZoomOptions}; 30 | pub use crs::Crs; 31 | pub use div_icon::{DivIcon, DivIconOptions}; 32 | pub use div_overlay::DivOverlay; 33 | pub use event::Event; 34 | pub use evented::{ 35 | DragEvents, Evented, EventedHandle, LayerEvents, MouseEvents, MoveEvents, PopupEvents, 36 | TooltipEvents, 37 | }; 38 | pub use feature_group::FeatureGroup; 39 | pub use geo_json::GeoJson; 40 | pub use grid_layer::{GridLayer, GridLayerOptions}; 41 | pub use handler::Handler; 42 | pub use icon::{Icon, IconOptions}; 43 | pub use lat_lng::LatLng; 44 | pub use lat_lng_bounds::LatLngBounds; 45 | pub use layer::{Layer, LayerOptions}; 46 | pub use layer_group::LayerGroup; 47 | pub use map::{ 48 | DragEndEvent, ErrorEvent, LocateOptions, LocationEvent, Map, MapOptions, MouseEvent, 49 | PopupEvent, TooltipEvent, 50 | }; 51 | pub use marker::{Marker, MarkerOptions}; 52 | pub use point::Point; 53 | pub use popup::{Popup, PopupOptions}; 54 | pub use raster::{ 55 | ImageOverlay, ImageOverlayOptions, TileLayer, TileLayerOptions, TileLayerWms, 56 | TileLayerWmsOptions, VideoOverlay, VideoOverlayOptions, WmsRequestBuilder, 57 | }; 58 | pub use shapes::{ 59 | Circle, CircleMarker, CircleOptions, Path, PathOptions, Polygon, Polyline, PolylineOptions, 60 | Rectangle, 61 | }; 62 | pub use tooltip::{Tooltip, TooltipOptions}; 63 | pub use util::Util; 64 | 65 | #[macro_export] 66 | macro_rules! object_property_set { 67 | ($a:ident, $b:ty) => { 68 | $crate::paste! { 69 | pub fn [](&mut self, val: $b) { 70 | let _ = js_sys::Reflect::set( 71 | self.as_ref(), 72 | &wasm_bindgen::JsValue::from(stringify!($a)), 73 | &wasm_bindgen::JsValue::from(val), 74 | ); 75 | } 76 | } 77 | }; 78 | ($a:ident, $b:ident, $c:ty) => { 79 | $crate::paste! { 80 | pub fn [](&mut self, val: $c) { 81 | let _ = js_sys::Reflect::set( 82 | self.as_ref(), 83 | &wasm_bindgen::JsValue::from(stringify!($b)), 84 | &wasm_bindgen::JsValue::from(val), 85 | ); 86 | } 87 | } 88 | }; 89 | } 90 | 91 | #[macro_export] 92 | macro_rules! create_object_with_properties { 93 | (($t:ident, $t_js:ident), $(($rust:ident, $js:ident, $b:ty)),+) => { 94 | $crate::paste! { 95 | #[wasm_bindgen] 96 | extern "C" { 97 | #[wasm_bindgen (extends = Object , js_name = $t_js)] 98 | #[derive(Debug, Clone, PartialEq, Eq)] 99 | pub type $t; 100 | 101 | $( 102 | #[wasm_bindgen(method, getter, js_name = $js)] 103 | pub fn $rust(this: &$t) -> $b; 104 | )* 105 | 106 | $( 107 | #[wasm_bindgen(method, setter, js_name = $js)] 108 | pub fn [](this: &$t, val: $b); 109 | )* 110 | } 111 | } 112 | impl $t { 113 | #[allow(clippy::new_without_default)] 114 | #[must_use] pub fn new() -> Self { 115 | #[allow(unused_mut)] 116 | let mut r = JsCast::unchecked_into(Object::new()); 117 | r 118 | } 119 | } 120 | }; 121 | (($t:ident, $t_js:ident, $t_extends:ident), $(($rust:ident, $js:ident, $b:ty)),+) => { 122 | $crate::paste! { 123 | #[wasm_bindgen] 124 | extern "C" { 125 | #[wasm_bindgen(extends = $t_extends, js_name = $t_js)] 126 | #[derive(Debug, Clone, PartialEq, Eq)] 127 | pub type $t; 128 | 129 | $( 130 | #[wasm_bindgen(method, getter, js_name = $js)] 131 | pub fn $rust(this: &$t) -> $b; 132 | )* 133 | 134 | $( 135 | #[wasm_bindgen(method, setter, js_name = $js)] 136 | pub fn [](this: &$t, val: $b); 137 | )* 138 | } 139 | } 140 | impl $t { 141 | #[allow(clippy::new_without_default)] 142 | #[must_use] pub fn new() -> Self { 143 | #[allow(unused_mut)] 144 | let mut r = JsCast::unchecked_into(Object::new()); 145 | r 146 | } 147 | } 148 | }; 149 | } 150 | 151 | #[macro_export] 152 | macro_rules! add_object_properties { 153 | ($t:ident, $(($rust:ident, $js:ident, $b:ty)),+) => { 154 | $crate::paste! { 155 | #[wasm_bindgen] 156 | extern "C" { 157 | $( 158 | #[wasm_bindgen(method, getter, js_name = $js)] 159 | pub fn $rust(this: &$t) -> $b; 160 | )* 161 | 162 | $( 163 | #[wasm_bindgen(method, setter, js_name = $js)] 164 | pub fn [](this: &$t, val: $b); 165 | )* 166 | } 167 | } 168 | }; 169 | } 170 | 171 | #[macro_export] 172 | macro_rules! object_property_set_with { 173 | ($a:ident, $b:ident, $c:expr) => { 174 | $crate::paste! { 175 | pub fn [](&mut self) { 176 | let _ = js_sys::Reflect::set( 177 | self.as_ref(), 178 | &wasm_bindgen::JsValue::from(stringify!($b)), 179 | &wasm_bindgen::JsValue::from($c), 180 | ); 181 | } 182 | } 183 | }; 184 | } 185 | 186 | #[macro_export] 187 | macro_rules! object_constructor { 188 | () => { 189 | #[allow(clippy::new_without_default)] 190 | #[must_use] 191 | pub fn new() -> Self { 192 | #[allow(unused_mut)] 193 | let mut r = JsCast::unchecked_into(Object::new()); 194 | r 195 | } 196 | }; 197 | } 198 | 199 | pub fn to_lat_lng_array + Clone>(lat_lngs: &[T]) -> Array { 200 | let array = Array::new(); 201 | for lat_lng in lat_lngs.iter().cloned() { 202 | array.push(&lat_lng.into()); 203 | } 204 | array 205 | } 206 | -------------------------------------------------------------------------------- /src/map/events.rs: -------------------------------------------------------------------------------- 1 | use crate::evented::LeafletEventHandler; 2 | use crate::{Event, LatLng, LocationEvent, Point, Popup, PopupEvents, Tooltip, TooltipEvents}; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use super::Map; 6 | 7 | #[wasm_bindgen] 8 | extern "C" { 9 | /// Mouse Event 10 | #[wasm_bindgen (extends = Event, js_name = MouseEvent)] 11 | #[derive(Debug, Clone, Eq, PartialEq)] 12 | pub type MouseEvent; 13 | 14 | #[wasm_bindgen(constructor)] 15 | pub fn new() -> MouseEvent; 16 | 17 | #[wasm_bindgen(method, getter, js_name = latlng)] 18 | pub fn lat_lng(this: &MouseEvent) -> LatLng; 19 | 20 | #[wasm_bindgen(method, setter, js_name = latlng)] 21 | pub fn set_lat_lng(this: &MouseEvent, value: &LatLng) -> MouseEvent; 22 | 23 | #[wasm_bindgen(method, getter, js_name = layerPoint)] 24 | pub fn layer_point(this: &MouseEvent) -> Point; 25 | 26 | #[wasm_bindgen(method, setter, js_name = layerPoint)] 27 | pub fn set_layer_point(this: &MouseEvent, value: &Point) -> MouseEvent; 28 | 29 | #[wasm_bindgen(method, getter, js_name = containerPoint)] 30 | pub fn container_point(this: &crate::map::events::MouseEvent) -> Point; 31 | 32 | #[wasm_bindgen(method, setter, js_name = containerPoint)] 33 | pub fn set_container_point(this: &MouseEvent, value: &Point) -> MouseEvent; 34 | 35 | #[wasm_bindgen(method, getter, js_name = originalEvent)] 36 | pub fn original_event(this: &MouseEvent) -> web_sys::MouseEvent; 37 | 38 | #[wasm_bindgen(method, setter, js_name = originalEvent)] 39 | pub fn set_original_event( 40 | this: &MouseEvent, 41 | value: &web_sys::MouseEvent, 42 | ) -> crate::map::events::MouseEvent; 43 | 44 | /// Error Event 45 | #[wasm_bindgen(extends = Event, js_name = ErrorEvent)] 46 | #[derive(Debug, Clone, Eq, PartialEq)] 47 | pub type ErrorEvent; 48 | 49 | #[wasm_bindgen(constructor)] 50 | pub fn new() -> ErrorEvent; 51 | 52 | #[wasm_bindgen(method, getter, js_name = message)] 53 | pub fn message(this: &ErrorEvent) -> String; 54 | 55 | #[wasm_bindgen(method, setter, js_name = message)] 56 | pub fn set_message(this: &ErrorEvent, value: &str); 57 | 58 | #[wasm_bindgen(method, getter, js_name = code)] 59 | pub fn code(this: &ErrorEvent) -> i32; 60 | 61 | #[wasm_bindgen(method, setter, js_name = code)] 62 | pub fn set_code(this: &ErrorEvent, value: i32); 63 | 64 | /// Drag End Event 65 | #[wasm_bindgen (extends = Event, js_name = DragEndEvent)] 66 | #[derive(Debug, Clone, Eq, PartialEq)] 67 | pub type DragEndEvent; 68 | 69 | #[wasm_bindgen(constructor)] 70 | pub fn new() -> DragEndEvent; 71 | 72 | /// The distance in pixels the draggable element was moved by. 73 | #[wasm_bindgen(method, getter, js_name = distance)] 74 | pub fn distance(this: &DragEndEvent) -> f64; 75 | 76 | #[wasm_bindgen(method, setter, js_name = distance)] 77 | pub fn set_distance(this: &DragEndEvent, value: f64); 78 | 79 | /// Reset Event 80 | #[wasm_bindgen (extends = Event, js_name = ResetEvent)] 81 | #[derive(Debug, Clone, Eq, PartialEq)] 82 | pub type ResetEvent; 83 | 84 | #[wasm_bindgen(constructor)] 85 | pub fn new() -> ResetEvent; 86 | 87 | #[wasm_bindgen(method, getter, js_name = oldSize)] 88 | pub fn old_size(this: &ResetEvent) -> Point; 89 | 90 | #[wasm_bindgen(method, setter, js_name = oldSize)] 91 | pub fn set_old_size(this: &ResetEvent, value: &Point); 92 | 93 | #[wasm_bindgen(method, getter, js_name = newSize)] 94 | pub fn new_size(this: &ResetEvent) -> Point; 95 | 96 | #[wasm_bindgen(method, setter, js_name = newSize)] 97 | pub fn set_new_size(this: &ResetEvent, value: &Point); 98 | 99 | /// Popup Event 100 | #[wasm_bindgen(extends = Event, js_name = PopupEvent)] 101 | #[derive(Debug, Clone, Eq, PartialEq)] 102 | pub type PopupEvent; 103 | 104 | #[wasm_bindgen(constructor)] 105 | pub fn new() -> PopupEvent; 106 | 107 | #[wasm_bindgen(method, getter, js_name = popup)] 108 | pub fn popup(this: &PopupEvent) -> Popup; 109 | 110 | #[wasm_bindgen(method, setter, js_name = popup)] 111 | pub fn set_popup(this: &PopupEvent, value: &Popup); 112 | 113 | /// Tooltip Event 114 | #[wasm_bindgen(extends = Event, js_name = TooltipEvent)] 115 | #[derive(Debug, Clone, Eq, PartialEq)] 116 | pub type TooltipEvent; 117 | 118 | #[wasm_bindgen(constructor)] 119 | pub fn new() -> TooltipEvent; 120 | 121 | #[wasm_bindgen(method, getter, js_name = tooltip)] 122 | pub fn tooltip(this: &TooltipEvent) -> Popup; 123 | 124 | #[wasm_bindgen(method, setter, js_name = tooltip)] 125 | pub fn set_tooltip(this: &TooltipEvent, value: &Tooltip); 126 | } 127 | 128 | impl Map { 129 | pub fn on_zoom_levels_change(&self, callback: Box) { 130 | let closure = Closure::wrap(callback); 131 | self.on("zoomlevelschange", &closure.into_js_value()); 132 | } 133 | 134 | pub fn on_resize(&self, callback: Box) { 135 | let closure = Closure::wrap(callback); 136 | self.on("resize", &closure.into_js_value()); 137 | } 138 | 139 | pub fn on_view_reset(&self, callback: Box) { 140 | let closure = Closure::wrap(callback); 141 | self.on("viewreset", &closure.into_js_value()); 142 | } 143 | 144 | pub fn on_load(&self, callback: Box) { 145 | let closure = Closure::wrap(callback); 146 | self.on("load", &closure.into_js_value()); 147 | } 148 | 149 | pub fn on_unload(&self, callback: Box) { 150 | let closure = Closure::wrap(callback); 151 | self.on("unload", &closure.into_js_value()); 152 | } 153 | 154 | pub fn on_zoom(&self, callback: Box) { 155 | let closure = Closure::wrap(callback); 156 | self.on("zoom", &closure.into_js_value()); 157 | } 158 | 159 | pub fn on_zoom_start(&self, callback: Box) { 160 | let closure = Closure::wrap(callback); 161 | self.on("zoomstart", &closure.into_js_value()); 162 | } 163 | 164 | pub fn on_zoom_end(&self, callback: Box) { 165 | let closure = Closure::wrap(callback); 166 | self.on("zoomend", &closure.into_js_value()); 167 | } 168 | 169 | pub fn on_move(&self, callback: Box) { 170 | let closure = Closure::wrap(callback); 171 | self.on("move", &closure.into_js_value()); 172 | } 173 | 174 | pub fn on_move_start(&self, callback: Box) { 175 | let closure = Closure::wrap(callback); 176 | self.on("movestart", &closure.into_js_value()); 177 | } 178 | 179 | pub fn on_move_end(&self, callback: Box) { 180 | let closure = Closure::wrap(callback); 181 | self.on("moveend", &closure.into_js_value()); 182 | } 183 | 184 | pub fn on_location_found(&self, callback: Box) { 185 | let closure = Closure::wrap(callback); 186 | self.on("locationfound", &closure.into_js_value()); 187 | } 188 | 189 | pub fn on_location_error(&self, callback: Box) { 190 | let closure = Closure::wrap(callback); 191 | self.on("locationerror", &closure.into_js_value()); 192 | } 193 | 194 | pub fn on_popup_open(&self, callback: Box) { 195 | let closure = Closure::wrap(callback); 196 | self.on("popupopen", &closure.into_js_value()); 197 | } 198 | 199 | pub fn on_popup_close(&self, callback: Box) { 200 | let closure = Closure::wrap(callback); 201 | self.on("popupclose", &closure.into_js_value()); 202 | } 203 | 204 | pub fn on_mouse_click(&self, callback: Box) { 205 | let closure = Closure::wrap(callback); 206 | self.on("click", &closure.into_js_value()); 207 | } 208 | 209 | pub fn on_mouse_double_click(&self, callback: Box) { 210 | let closure = Closure::wrap(callback); 211 | self.on("dblclick", &closure.into_js_value()); 212 | } 213 | 214 | pub fn on_mouse_context_menu(&self, callback: Box) { 215 | let closure = Closure::wrap(callback); 216 | self.on("contextmenu", &closure.into_js_value()); 217 | } 218 | 219 | pub fn on_mouse_move(&self, callback: Box) { 220 | let closure = Closure::wrap(callback); 221 | self.on("mousemove", &closure.into_js_value()); 222 | } 223 | 224 | pub fn on_mouse_over(&self, callback: Box) { 225 | let closure = Closure::wrap(callback); 226 | self.on("mouseover", &closure.into_js_value()); 227 | } 228 | 229 | pub fn on_mouse_out(&self, callback: Box) { 230 | let closure = Closure::wrap(callback); 231 | self.on("mouseout", &closure.into_js_value()); 232 | } 233 | 234 | pub fn on_mouse_down(&self, callback: Box) { 235 | let closure = Closure::wrap(callback); 236 | self.on("mousedown", &closure.into_js_value()); 237 | } 238 | 239 | pub fn on_mouse_up(&self, callback: Box) { 240 | let closure = Closure::wrap(callback); 241 | self.on("mouseup", &closure.into_js_value()); 242 | } 243 | } 244 | 245 | impl LeafletEventHandler for Map { 246 | fn on(&self, event: &str, callback: &JsValue) { 247 | self.obj.on(event, callback); 248 | } 249 | } 250 | 251 | impl TooltipEvents for Map {} 252 | impl PopupEvents for Map {} 253 | -------------------------------------------------------------------------------- /src/map/geolocation.rs: -------------------------------------------------------------------------------- 1 | use js_sys::{Object, Reflect}; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::{object_constructor, Map}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | 9 | #[wasm_bindgen (extends = Object , js_name = LocateOptions)] 10 | #[derive(Debug, Clone, Eq, PartialEq)] 11 | pub type LocateOptions; 12 | 13 | #[wasm_bindgen(method, js_name = locate)] 14 | pub fn locate(this: &Map) -> Map; 15 | 16 | /// Tries to locate the user using the Geolocation API, firing a 17 | /// locationfound event with location data on success or a `locationerror` 18 | /// event on failure, and optionally sets the map view to the user's 19 | /// location with respect to detection accuracy (or to the world view if 20 | /// geolocation failed). Note that, if your page doesn't use HTTPS, this 21 | /// method will fail in modern browsers (Chrome 50 and newer) 22 | /// See `LocateOptions` for more details. 23 | #[wasm_bindgen(method, js_name = locate)] 24 | pub fn locate_with_options(this: &Map, options: &LocateOptions) -> Map; 25 | 26 | /// Stops watching location previously initiated by map.locate({watch: true}) 27 | /// and aborts resetting the map view if map.locate was called with {setView: true}. 28 | #[wasm_bindgen(method, js_name = stopLocate)] 29 | pub fn stop_locate(this: &Map) -> Map; 30 | } 31 | 32 | impl LocateOptions { 33 | object_constructor!(); 34 | 35 | /// If true, starts continuous watching of location changes (instead of detecting it once) 36 | /// using W3C watchPosition method. You can later stop watching using `map.stopLocate()` method. 37 | /// 38 | /// [Leaflet Documentation](https://leafletjs.com/reference.html#locate-options-watch) 39 | pub fn watch(&mut self, val: bool) -> &mut Self { 40 | let r = Reflect::set(self.as_ref(), &JsValue::from("watch"), &JsValue::from(val)); 41 | let _ = r; 42 | self 43 | } 44 | 45 | /// If true, automatically sets the map view to the user location with respect to 46 | /// detection accuracy, or to world view if geolocation failed. 47 | /// 48 | /// [Leaflet Documentation](https://leafletjs.com/reference.html#locate-options-setView) 49 | pub fn set_view(&mut self, val: bool) -> &mut Self { 50 | let r = Reflect::set( 51 | self.as_ref(), 52 | &JsValue::from("setView"), 53 | &JsValue::from(val), 54 | ); 55 | let _ = r; 56 | self 57 | } 58 | 59 | /// The maximum zoom for automatic view setting when using setView option. 60 | /// 61 | /// [Leaflet Documentation](https://leafletjs.com/reference.html#locate-options-maxZoom) 62 | pub fn max_zoom(&mut self, val: f64) -> &mut Self { 63 | let r = Reflect::set( 64 | self.as_ref(), 65 | &JsValue::from("maxZoom"), 66 | &JsValue::from(val), 67 | ); 68 | let _ = r; 69 | self 70 | } 71 | 72 | /// Number of milliseconds to wait for a response from geolocation before firing a `locationerror` event. 73 | /// 74 | /// [Leaflet Documentation](https://leafletjs.com/reference.html#locate-options-timeout) 75 | pub fn timeout(&mut self, val: f64) -> &mut Self { 76 | let r = Reflect::set( 77 | self.as_ref(), 78 | &JsValue::from("timeout"), 79 | &JsValue::from(val), 80 | ); 81 | let _ = r; 82 | self 83 | } 84 | 85 | /// Maximum age of detected location. If less than this amount of milliseconds passed since 86 | /// last geolocation response, locate will return a cached location. 87 | /// 88 | /// [Leaflet Documentation](https://leafletjs.com/reference.html#locate-options-maximumAge) 89 | pub fn maximum_age(&mut self, val: f64) -> &mut Self { 90 | let r = Reflect::set( 91 | self.as_ref(), 92 | &JsValue::from("maximumAge"), 93 | &JsValue::from(val), 94 | ); 95 | let _ = r; 96 | self 97 | } 98 | 99 | /// Enables high accuracy, see [description in the W3C spec](https://w3c.github.io/geolocation-api/#enablehighaccuracy-member). 100 | /// 101 | /// [Leaflet Documentation](https://leafletjs.com/reference.html#locate-options-enableHighAccuracy) 102 | pub fn enable_high_accuracy(&mut self, val: bool) -> &mut Self { 103 | let r = Reflect::set( 104 | self.as_ref(), 105 | &JsValue::from("enableHighAccuracy"), 106 | &JsValue::from(val), 107 | ); 108 | let _ = r; 109 | self 110 | } 111 | } 112 | 113 | impl Default for LocateOptions { 114 | fn default() -> Self { 115 | LocateOptions::new() 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/map/location_event.rs: -------------------------------------------------------------------------------- 1 | use crate::{Event, LatLng, LatLngBounds}; 2 | use wasm_bindgen::prelude::*; 3 | 4 | #[wasm_bindgen] 5 | extern "C" { 6 | #[wasm_bindgen (extends = Event, js_name = LocationEvent)] 7 | #[derive(Debug, Clone, Eq, PartialEq)] 8 | pub type LocationEvent; 9 | 10 | #[wasm_bindgen(constructor)] 11 | pub fn new() -> LocationEvent; 12 | 13 | #[wasm_bindgen(method, getter, js_name = latlng)] 14 | pub fn lat_lng(this: &LocationEvent) -> LatLng; 15 | 16 | #[wasm_bindgen(method, setter,js_name = latlng)] 17 | pub fn set_lat_lng(this: &LocationEvent, lat_lng: &LatLng); 18 | 19 | #[wasm_bindgen(method, getter, js_name = bounds)] 20 | pub fn bounds(this: &LocationEvent) -> LatLngBounds; 21 | 22 | #[wasm_bindgen(method, setter,js_name = bounds)] 23 | pub fn set_bounds(this: &LocationEvent, value: &LatLngBounds); 24 | 25 | #[wasm_bindgen(method, getter, js_name = accuracy)] 26 | pub fn accuracy(this: &LocationEvent) -> f64; 27 | 28 | #[wasm_bindgen(method, setter,js_name = accuracy)] 29 | pub fn set_accuracy(this: &LocationEvent, value: f64); 30 | 31 | #[wasm_bindgen(method, getter, js_name = altitude)] 32 | pub fn altitude(this: &LocationEvent) -> f64; 33 | 34 | #[wasm_bindgen(method, setter,js_name = altitude)] 35 | pub fn set_altitude(this: &LocationEvent, value: f64); 36 | 37 | #[wasm_bindgen(method, getter, js_name = altitudeAccuracy)] 38 | pub fn altitude_accuracy(this: &LocationEvent) -> f64; 39 | 40 | #[wasm_bindgen(method, setter,js_name = altitudeAccuracy)] 41 | pub fn set_altitude_accuracy(this: &LocationEvent, value: f64); 42 | 43 | #[wasm_bindgen(method, getter, js_name = heading)] 44 | pub fn heading(this: &LocationEvent) -> f64; 45 | 46 | #[wasm_bindgen(method, setter,js_name = heading)] 47 | pub fn set_heading(this: &LocationEvent, value: f64); 48 | 49 | #[wasm_bindgen(method, getter, js_name = speed)] 50 | pub fn speed(this: &LocationEvent) -> f64; 51 | 52 | #[wasm_bindgen(method, setter,js_name = speed)] 53 | pub fn set_speed(this: &LocationEvent, value: f64); 54 | 55 | #[wasm_bindgen(method, getter, js_name = timestamp)] 56 | pub fn timestamp(this: &LocationEvent) -> f64; 57 | 58 | #[wasm_bindgen(method, setter,js_name = timestamp)] 59 | pub fn set_timestamp(this: &LocationEvent, value: f64); 60 | } 61 | -------------------------------------------------------------------------------- /src/map/mod.rs: -------------------------------------------------------------------------------- 1 | mod events; 2 | mod geolocation; 3 | mod location_event; 4 | mod other; 5 | 6 | use js_sys::{Array, Object}; 7 | use wasm_bindgen::prelude::*; 8 | use web_sys::HtmlElement; 9 | 10 | use crate::{ 11 | create_object_with_properties, object_property_set_with, Control, Evented, LatLng, 12 | LatLngBounds, Layer, Point, Popup, Tooltip, 13 | }; 14 | pub use events::*; 15 | pub use geolocation::*; 16 | pub use location_event::*; 17 | 18 | #[wasm_bindgen] 19 | extern "C" { 20 | #[wasm_bindgen(extends=Evented)] 21 | #[derive(Debug, Clone)] 22 | pub type Map; 23 | 24 | #[wasm_bindgen(constructor, js_namespace = L)] 25 | pub fn new(id: &str, options: &MapOptions) -> Map; 26 | 27 | #[wasm_bindgen(constructor, js_namespace = L)] 28 | pub fn new_with_element(el: &HtmlElement, options: &MapOptions) -> Map; 29 | 30 | // Methods for Layers and Controls 31 | #[wasm_bindgen(method, js_name = addControl)] 32 | pub fn add_control(this: &Map, control: &Control) -> Map; 33 | 34 | #[wasm_bindgen(method, js_name = removeControl)] 35 | pub fn remove_control(this: &Map, control: &Control) -> Map; 36 | 37 | #[wasm_bindgen(method, js_name = addLayer)] 38 | pub fn add_layer(this: &Map, layer: &Layer) -> Map; 39 | 40 | #[wasm_bindgen(method, js_name = removeLayer)] 41 | pub fn remove_layer(this: &Map, layer: &Layer) -> Map; 42 | 43 | #[wasm_bindgen(method, js_name = hasLayer)] 44 | pub fn has_layer(this: &Map, layer: &Layer) -> bool; 45 | 46 | #[wasm_bindgen(method, js_name = eachLayer)] 47 | pub fn each_layer(this: &Map, for_each: &dyn Fn(Layer)) -> Map; 48 | 49 | #[wasm_bindgen(method, js_name = eachLayer)] 50 | pub fn each_layer_with_context(this: &Map, for_each: &dyn Fn(Layer), context: &JsValue) -> Map; 51 | 52 | #[wasm_bindgen(method, js_name = openPopup)] 53 | pub fn open_popup(this: &Map, popup: &Popup) -> Map; 54 | 55 | #[wasm_bindgen(method, js_name = openPopup)] 56 | pub fn open_popup_with_content(this: &Map, content: &JsValue, lat_lng: &LatLng) -> Map; 57 | 58 | #[wasm_bindgen(method, js_name = openPopup)] 59 | pub fn open_popup_with_content_and_options( 60 | this: &Map, 61 | content: &JsValue, 62 | lat_lng: &LatLng, 63 | options: &JsValue, 64 | ) -> Map; 65 | 66 | #[wasm_bindgen(method, js_name = closePopup)] 67 | pub fn close_popup(this: &Map, popup: &Popup) -> Map; 68 | 69 | #[wasm_bindgen(method, js_name = openTooltip)] 70 | pub fn open_tooltip(this: &Map, tooltip: &Tooltip) -> Map; 71 | 72 | #[wasm_bindgen(method, js_name = openTooltip)] 73 | pub fn open_tooltip_with_content(this: &Map, content: &JsValue, lat_lng: &LatLng) -> Map; 74 | 75 | #[wasm_bindgen(method, js_name = openTooltip)] 76 | pub fn open_tooltip_with_content_and_options( 77 | this: &Map, 78 | content: &JsValue, 79 | lat_lng: &LatLng, 80 | options: &JsValue, 81 | ) -> Map; 82 | 83 | #[wasm_bindgen(method, js_name = closeTooltip)] 84 | pub fn close_tooltip(this: &Map, tooltip: &Tooltip) -> Map; 85 | 86 | // Methods for modifying map state 87 | 88 | #[wasm_bindgen(method, js_name = setView)] 89 | pub fn set_view(this: &Map, center: &LatLng, zoom: f64) -> Map; 90 | 91 | #[wasm_bindgen(method, js_name = setView)] 92 | pub fn set_view_with_options(this: &Map, center: &LatLng, zoom: f64, options: &JsValue) -> Map; 93 | 94 | #[wasm_bindgen(method, js_name = getBounds)] 95 | pub fn get_bounds(this: &Map) -> LatLngBounds; 96 | 97 | #[wasm_bindgen(method, js_name = getCenter)] 98 | pub fn get_center(this: &Map) -> LatLng; 99 | 100 | #[wasm_bindgen(method, js_name = getZoom)] 101 | pub fn get_zoom(this: &Map) -> f64; 102 | 103 | #[wasm_bindgen(method, js_name = getZoomScale)] 104 | pub fn get_zoom_scale(this: &Map, toZoom: f64, fromZoom: f64) -> f64; 105 | 106 | #[wasm_bindgen(method, js_name = setZoom)] 107 | pub fn set_zoom(this: &Map, zoom: f64) -> Map; 108 | 109 | #[wasm_bindgen(method, js_name = setZoom)] 110 | pub fn set_zoom_with_options(this: &Map, zoom: f64, options: &JsValue) -> Map; 111 | 112 | #[wasm_bindgen(method, js_name = zoomIn)] 113 | pub fn zoom_in(this: &Map, delta: f64) -> Map; 114 | 115 | #[wasm_bindgen(method, js_name = zoomIn)] 116 | pub fn zoom_in_with_options(this: &Map, delta: f64, options: &JsValue) -> Map; 117 | 118 | #[wasm_bindgen(method, js_name = zoomOut)] 119 | pub fn zoom_out(this: &Map, delta: f64); 120 | 121 | #[wasm_bindgen(method, js_name = zoomOut)] 122 | pub fn zoom_out_with_options(this: &Map, delta: f64, options: &JsValue) -> Map; 123 | 124 | #[wasm_bindgen(method, js_name = setZoomAround)] 125 | pub fn set_zoom_around_lat_lng(this: &Map, latlng: &LatLng, zoom: f64) -> Map; 126 | 127 | #[wasm_bindgen(method, js_name = setZoomAround)] 128 | pub fn set_zoom_around_lat_lng_with_options( 129 | this: &Map, 130 | latlng: &LatLng, 131 | zoom: f64, 132 | options: &JsValue, 133 | ) -> Map; 134 | 135 | #[wasm_bindgen(method, js_name = setZoomAround)] 136 | pub fn set_zoom_around_point(this: &Map, offset: &Point, zoom: f64) -> Map; 137 | 138 | #[wasm_bindgen(method, js_name = setZoomAround)] 139 | pub fn set_zoom_around_point_with_options( 140 | this: &Map, 141 | offset: &Point, 142 | zoom: f64, 143 | options: &JsValue, 144 | ) -> Map; 145 | 146 | #[wasm_bindgen(method, js_name = "fitBounds")] 147 | pub fn fit_bounds(this: &Map, bounds: &LatLngBounds) -> Map; 148 | 149 | #[wasm_bindgen(method, js_name = fitBounds)] 150 | pub fn fit_bounds_with_options(this: &Map, bounds: &LatLngBounds, options: &JsValue) -> Map; 151 | 152 | #[wasm_bindgen(method, js_name = fitWorld)] 153 | pub fn fit_world(this: &Map) -> Map; 154 | 155 | #[wasm_bindgen(method, js_name = fitWorld)] 156 | pub fn fit_world_with_options(this: &Map, options: &JsValue) -> Map; 157 | 158 | #[wasm_bindgen(method, js_name = panTo)] 159 | pub fn pan_to(this: &Map, lat_lng: &LatLng) -> Map; 160 | 161 | #[wasm_bindgen(method, js_name = panTo)] 162 | pub fn pan_to_with_options(this: &Map, lat_lng: &LatLng, options: &JsValue) -> Map; 163 | 164 | #[wasm_bindgen(method, js_name = panBy)] 165 | pub fn pan_by(this: &Map, point: &Point) -> Map; 166 | 167 | #[wasm_bindgen(method, js_name = panBy)] 168 | pub fn pan_by_with_options(this: &Map, point: &Point, options: &JsValue) -> Map; 169 | 170 | #[wasm_bindgen(method, js_name = flyTo)] 171 | pub fn fly_to(this: &Map, lat_lng: &LatLng, zoom: f64) -> Map; 172 | 173 | #[wasm_bindgen(method, js_name = flyTo)] 174 | pub fn fly_to_with_options(this: &Map, latlng: &LatLng, zoom: f64, options: &JsValue) -> Map; 175 | 176 | #[wasm_bindgen(method, js_name = flyToBounds)] 177 | pub fn fly_to_bounds(this: &Map, bounds: &LatLngBounds) -> Map; 178 | 179 | #[wasm_bindgen(method, js_name = flyToBounds)] 180 | pub fn fly_to_bounds_with_options(this: &Map, bounds: &LatLngBounds, options: &JsValue) -> Map; 181 | 182 | #[wasm_bindgen(method, js_name = setMaxBounds)] 183 | pub fn set_max_bounds(this: &Map, bounds: &LatLngBounds) -> Map; 184 | 185 | #[wasm_bindgen(method, js_name = setMinZoom)] 186 | pub fn set_min_zoom(this: &Map, zoom: f64) -> Map; 187 | 188 | #[wasm_bindgen(method, js_name = setMaxZoom)] 189 | pub fn set_max_zoom(this: &Map, zoom: f64) -> Map; 190 | 191 | /// [`getMaxZoom`](https://leafletjs.com/reference-1.7.1.html#map-getmaxzoom) 192 | #[wasm_bindgen(method, js_name = getMaxZoom)] 193 | pub fn get_max_zoom(this: &Map) -> f64; 194 | 195 | #[wasm_bindgen(method, js_name = panInsideBounds)] 196 | pub fn pan_inside_bounds(this: &Map, bounds: &LatLngBounds) -> Map; 197 | 198 | #[wasm_bindgen(method, js_name = panInsideBounds)] 199 | pub fn pan_inside_bounds_with_options( 200 | this: &Map, 201 | bounds: &LatLngBounds, 202 | options: &JsValue, 203 | ) -> Map; 204 | 205 | #[wasm_bindgen(method, js_name = panInside)] 206 | pub fn pan_inside(this: &Map, latlng: &LatLng) -> Map; 207 | 208 | #[wasm_bindgen(method, js_name = panInside)] 209 | pub fn pan_inside_with_options(this: &Map, latlng: &LatLng, options: &JsValue) -> Map; 210 | 211 | #[wasm_bindgen(method, js_name = invalidateSize)] 212 | pub fn invalidate_size(this: &Map, animate: bool) -> Map; 213 | 214 | #[wasm_bindgen(method, js_name = invalidateSize)] 215 | pub fn invalidate_size_with_options(this: &Map, options: &JsValue) -> Map; 216 | 217 | #[wasm_bindgen(method)] 218 | pub fn stop(this: &Map) -> Map; 219 | 220 | #[wasm_bindgen(method)] 221 | pub fn project(this: &Map, point: &LatLng) -> Point; 222 | 223 | #[wasm_bindgen(method)] 224 | pub fn unproject(this: &Map, point: &Point) -> LatLng; 225 | 226 | #[wasm_bindgen(method, js_name = project)] 227 | pub fn project_with_zoom(this: &Map, point: &LatLng, zoom: f64) -> Point; 228 | 229 | #[wasm_bindgen(method, js_name = unproject)] 230 | pub fn unproject_with_zoom(this: &Map, point: &Point, zoom: f64) -> LatLng; 231 | 232 | #[wasm_bindgen(method)] 233 | pub fn distance(this: &Map, latlng1: &LatLng, latlng2: &LatLng) -> f64; 234 | 235 | #[wasm_bindgen(method, js_name = latLngToContainerPoint)] 236 | pub fn lat_lng_to_container_point(this: &Map, latlng: &LatLng) -> Point; 237 | 238 | #[wasm_bindgen(method, js_name = containerPointToLatLng)] 239 | pub fn container_point_to_lat_lng(this: &Map, point: &Point) -> LatLng; 240 | 241 | #[wasm_bindgen(method, js_name = layerPointToLatLng)] 242 | pub fn layer_point_to_lat_lng(this: &Map, point: &Point) -> LatLng; 243 | 244 | #[wasm_bindgen(method, js_name = latLngToLayerPoint)] 245 | pub fn lat_lng_to_layer_point(this: &Map, latlng: &LatLng) -> Point; 246 | 247 | #[wasm_bindgen(method, js_name = getSize)] 248 | pub fn get_size(this: &Map) -> Point; 249 | } 250 | 251 | create_object_with_properties!( 252 | (MapOptions, MapOptions), 253 | // Options 254 | (prefer_canvas, preferCanvas, bool), 255 | // Control options 256 | (attribution_control, attributionControl, bool), 257 | (zoom_control, zoomControl, bool), 258 | // Interaction Options 259 | (close_popup_on_click, closePopupOnClick, bool), 260 | (box_zoom, boxZoom, bool), 261 | (double_click_zoom, doubleClickZoom, JsValue), 262 | (dragging, dragging, bool), 263 | (zoom_snap, zoomSnap, f64), 264 | (zoom_delta, zoomDelta, f64), 265 | (track_resize, trackResize, bool), 266 | // Panning Inertia Options 267 | (inertia, inertia, bool), 268 | (inertia_deceleration, inertiaDeceleration, f64), 269 | (inertia_max_speed, inertiaMaxSpeed, f64), 270 | (ease_linearity, easeLinearity, f64), 271 | (world_copy_jump, worldCopyJump, bool), 272 | (max_bounds_viscosity, maxBoundsViscosity, f64), 273 | // Keyboard Navigation Options 274 | (keyboard, keyboard, bool), 275 | (keyboard_pan_delta, keyboardPanDelta, f64), 276 | // Mouse wheel options 277 | (scroll_wheel_zoom, scrollWheelZoom, bool), 278 | (wheel_debounce_time, wheelDebounceTime, f64), 279 | (wheel_px_per_zoom_level, wheelPxPerZoomLevel, f64), 280 | // Touch interaction options 281 | (tap_hold, tapHold, bool), 282 | (tap_tolerance, tapTolerance, f64), 283 | (touch_zoom, touchZoom, bool), 284 | (bounce_at_zoom_limits, bounceAtZoomLimits, bool), 285 | // Map State Options 286 | (crs, crs, JsValue), 287 | (center, center, LatLng), 288 | (zoom, zoom, f64), 289 | (min_zoom, minZoom, f64), 290 | (max_zoom, maxZoom, f64), 291 | (layers, layers, Array), 292 | (max_bounds, maxBounds, LatLngBounds), 293 | (renderer, renderer, JsValue), 294 | // Animation Options 295 | (zoom_animation, zoomAnimation, bool), 296 | (zoom_animation_threshold, zoomAnimationThreshold, f64), 297 | (fade_animation, fadeAnimation, bool), 298 | (marker_zoom_animation, markerZoomAnimation, bool), 299 | (transform3d_limit, transform3DLimit, f64) 300 | ); 301 | 302 | impl MapOptions { 303 | object_property_set_with!(scroll_wheel_zoom_center, scrollWheelZoom, "center"); 304 | object_property_set_with!(touch_zoom_center, touchZoom, "center"); 305 | } 306 | 307 | impl Default for MapOptions { 308 | fn default() -> Self { 309 | MapOptions::new() 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /src/map/other.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | use web_sys::HtmlElement; 4 | 5 | use crate::Map; 6 | 7 | #[wasm_bindgen] 8 | extern "C" { 9 | 10 | #[wasm_bindgen(method, js_name = addHandler)] 11 | pub fn add_handler(this: &Map, name: &str, handler_class: &Closure) -> Map; 12 | 13 | #[wasm_bindgen(method, js_name = remove)] 14 | pub fn remove(this: &Map) -> Map; 15 | 16 | #[wasm_bindgen(method, js_name = createPane)] 17 | pub fn create_pane(this: &Map, name: &str, container: &HtmlElement) -> HtmlElement; 18 | 19 | #[wasm_bindgen(method, js_name = getPane)] 20 | pub fn get_pane(this: &Map, pane: &HtmlElement) -> HtmlElement; 21 | 22 | #[wasm_bindgen(method, js_name = getPane)] 23 | pub fn get_pane_by_name(this: &Map, name: &str) -> HtmlElement; 24 | 25 | #[wasm_bindgen(method, js_name = getPanes)] 26 | pub fn get_panes(this: &Map) -> Object; 27 | 28 | #[wasm_bindgen(method, js_name = getContainer)] 29 | pub fn get_container(this: &Map) -> HtmlElement; 30 | 31 | #[wasm_bindgen(method, js_name = whenReady)] 32 | pub fn when_ready(this: &Map, callback: &Closure) -> Map; 33 | 34 | #[wasm_bindgen(method, js_name = whenReady)] 35 | pub fn when_ready_with_context( 36 | this: &Map, 37 | callback: &Closure, 38 | context: &JsValue, 39 | ) -> Map; 40 | } 41 | -------------------------------------------------------------------------------- /src/marker.rs: -------------------------------------------------------------------------------- 1 | use crate::evented::{ 2 | DragEvents, LeafletEventHandler, MouseEvents, MoveEvents, PopupEvents, TooltipEvents, 3 | }; 4 | use crate::{ 5 | create_object_with_properties, Evented, Handler, Icon, LatLng, Layer, LayerEvents, Point, 6 | }; 7 | use js_sys::Object; 8 | use wasm_bindgen::prelude::*; 9 | 10 | #[wasm_bindgen] 11 | extern "C" { 12 | // Marker 13 | #[derive(Debug, Clone, PartialEq)] 14 | #[wasm_bindgen(extends = Layer)] 15 | pub type Marker; 16 | 17 | // [`Marker`](https://leafletjs.com/reference.html#marker-l-marker) 18 | #[wasm_bindgen(constructor, js_namespace = L)] 19 | pub fn new(lat_lng: &LatLng) -> Marker; 20 | 21 | // [`Marker`](https://leafletjs.com/reference.html#marker-l-marker) 22 | #[wasm_bindgen(constructor, js_namespace = L)] 23 | pub fn new_with_options(lat_lng: &LatLng, options: &MarkerOptions) -> Marker; 24 | 25 | /// ['setIcon'](https://leafletjs.com/reference.html#marker-seticon) 26 | #[wasm_bindgen(method, js_name = setIcon)] 27 | pub fn set_icon(this: &Marker, icon: &Icon); 28 | 29 | /// ['setIcon'](https://leafletjs.com/reference.html#marker-setopacity) 30 | #[wasm_bindgen(method, js_name = setOpacity)] 31 | pub fn set_opacity(this: &Marker, value: f64); 32 | 33 | /// ['getLatLng'](https://leafletjs.com/reference.html#marker-getlatlng) 34 | #[wasm_bindgen(method, js_name = getLatLng)] 35 | pub fn get_lat_lng(this: &Marker) -> LatLng; 36 | 37 | /// ['setLatLng'](https://leafletjs.com/reference.html#marker-setlatlng) 38 | #[wasm_bindgen(method, js_name = setLatLng)] 39 | pub fn set_lat_lng(this: &Marker, latlng: &LatLng); 40 | 41 | /// ['dragging'](https://leafletjs.com/reference.html#marker-dragging) 42 | #[wasm_bindgen(method, getter)] 43 | pub fn dragging(this: &Marker) -> Handler; 44 | 45 | #[wasm_bindgen(method)] 46 | pub fn update(this: &Marker) -> Marker; 47 | 48 | #[wasm_bindgen(method, js_name = setZIndexOffset)] 49 | pub fn set_z_index_offset(this: &Marker, offset: f64) -> Marker; 50 | } 51 | 52 | create_object_with_properties!( 53 | (MarkerOptions, MarkerOptions), 54 | // [`icon`](https://leafletjs.com/reference.html#marker-icon) 55 | (icon, icon, Icon), 56 | // ['keyboard'](https://leafletjs.com/reference.html#marker-keyboard) 57 | (keyboard, keyboard, bool), 58 | // ['title'](https://leafletjs.com/reference.html#marker-title) 59 | (title, title, String), 60 | // ['alt'](https://leafletjs.com/reference.html#marker-alt) 61 | (alt, alt, String), 62 | // ['zIndexOffset'](https://leafletjs.com/reference.html#marker-zindexoffset) 63 | (z_index_offset, zIndexOffset, f64), 64 | // ['opacity'](https://leafletjs.com/reference.html#marker-opacity) 65 | (opacity, opacity, f64), 66 | // ['riseOnHover'](https://leafletjs.com/reference.html#marker-riseonhover) 67 | (rise_on_hover, riseOnHover, bool), 68 | // ['riseOffset'](https://leafletjs.com/reference.html#marker-riseoffset) 69 | (rise_offset, riseOffset, f64), 70 | // ['pane'](https://leafletjs.com/reference.html#marker-pane) 71 | (pane, pane, String), 72 | // ['shadowPane'](https://leafletjs.com/reference.html#marker-shadowpane) 73 | (shadow_pane, shadowPane, String), 74 | // ['bubblingMouseEvents'](https://leafletjs.com/reference.html#marker-bubblingmouseevents) 75 | (bubbling_mouse_events, bubblingMouseEvents, bool), 76 | // Draggable marker options 77 | // ['draggable'](https://leafletjs.com/reference.html#marker-draggable) 78 | (draggable, draggable, bool), 79 | // ['autoPan'](https://leafletjs.com/reference.html#marker-autopan) 80 | (auto_pan, autoPan, bool), 81 | // ['autoPanPadding'](https://leafletjs.com/reference.html#marker-autopanpadding) 82 | (auto_pan_padding, autoPanPadding, Point), 83 | // ['autoPanSpeed'](https://leafletjs.com/reference.html#marker-autopanspeed) 84 | (auto_pan_speed, autoPanSpeed, f64), 85 | // Interactive layer 86 | // ['interactive'](https://leafletjs.com/reference.html#marker-interactive) 87 | (interactive, interactive, bool), 88 | // Layer 89 | // ['attribution'](https://leafletjs.com/reference.html#marker-attribution) 90 | (attribution, attribution, String) 91 | ); 92 | 93 | impl Default for MarkerOptions { 94 | fn default() -> Self { 95 | Self::new() 96 | } 97 | } 98 | 99 | impl LeafletEventHandler for Marker { 100 | fn on(&self, event: &str, callback: &JsValue) { 101 | self.unchecked_ref::().on(event, callback); 102 | } 103 | } 104 | 105 | impl MoveEvents for Marker {} 106 | impl MouseEvents for Marker {} 107 | impl DragEvents for Marker {} 108 | impl LayerEvents for Marker {} 109 | impl PopupEvents for Marker {} 110 | impl TooltipEvents for Marker {} 111 | -------------------------------------------------------------------------------- /src/point.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen] 4 | extern "C" { 5 | #[derive(Debug)] 6 | pub type Point; 7 | 8 | #[wasm_bindgen(constructor, js_namespace = L)] 9 | pub fn new(x: f64, y: f64) -> Point; 10 | 11 | #[wasm_bindgen(method, getter)] 12 | pub fn x(this: &Point) -> f64; 13 | 14 | #[wasm_bindgen(method, getter)] 15 | pub fn y(this: &Point) -> f64; 16 | 17 | #[wasm_bindgen(method)] 18 | pub fn add(this: &Point, other: &Point) -> Point; 19 | 20 | #[wasm_bindgen(method)] 21 | pub fn subtract(this: &Point, other: &Point) -> Point; 22 | 23 | #[wasm_bindgen(method, js_name = multiplyBy)] 24 | pub fn multiply_by(this: &Point, scalar: f64) -> Point; 25 | 26 | #[wasm_bindgen(method, js_name = divideBy)] 27 | pub fn divide_by(this: &Point, scalar: f64) -> Point; 28 | 29 | #[wasm_bindgen(method, js_name = scaleBy)] 30 | pub fn scale_by(this: &Point, other: &Point) -> Point; 31 | 32 | #[wasm_bindgen(method, js_name = unscaleByTo)] 33 | pub fn unscale_by_to(this: &Point, other: &Point) -> Point; 34 | 35 | #[wasm_bindgen(method)] 36 | pub fn round(this: &Point) -> Point; 37 | 38 | #[wasm_bindgen(method)] 39 | pub fn floor(this: &Point) -> Point; 40 | 41 | #[wasm_bindgen(method)] 42 | pub fn ceil(this: &Point) -> Point; 43 | 44 | #[wasm_bindgen(method)] 45 | pub fn trunc(this: &Point) -> bool; 46 | 47 | #[wasm_bindgen(method)] 48 | pub fn equals(this: &Point, other: &Point) -> bool; 49 | 50 | #[wasm_bindgen(method)] 51 | pub fn contains(this: &Point, other: &Point) -> f64; 52 | 53 | #[wasm_bindgen(method, js_name = distanceTo)] 54 | pub fn distance_to(this: &Point, other: &Point) -> f64; 55 | } 56 | 57 | impl From<(u32, u32)> for Point { 58 | fn from((x, y): (u32, u32)) -> Point { 59 | Point::new(f64::from(x), f64::from(y)) 60 | } 61 | } 62 | 63 | impl From<(f64, f64)> for Point { 64 | fn from((x, y): (f64, f64)) -> Point { 65 | Point::new(x, y) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/popup.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::{create_object_with_properties, DivOverlay, LatLng, Layer, Point}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | // Popup 9 | /// [`Popup`](https://leafletjs.com/reference.html#popup) 10 | #[derive(Debug, Clone)] 11 | #[wasm_bindgen(extends = DivOverlay)] 12 | pub type Popup; 13 | 14 | /// [`L.popup`](https://leafletjs.com/reference.html#popup-l-popup) 15 | #[wasm_bindgen(constructor, js_namespace = L)] 16 | pub fn new(options: &PopupOptions, layer: Option<&Layer>) -> Popup; 17 | 18 | /// [`L.popup`](/// [`L.popup`](https://leafletjs.com/reference.html#popup-l-popup)) 19 | #[wasm_bindgen(constructor, js_namespace = L)] 20 | pub fn new_with_lat_lng(lat_lng: &LatLng, options: &PopupOptions) -> Popup; 21 | } 22 | 23 | create_object_with_properties!( 24 | (PopupOptions, PopupOptions), 25 | (pane, pane, String), 26 | (offset, offset, Point), 27 | (min_width, minWidth, f64), 28 | (max_width, maxWidth, f64), 29 | (max_height, maxHeight, f64), 30 | (auto_pan, autoPan, bool), 31 | (auto_pan_padding_top_left, autoPanPaddingTopLeft, Point), 32 | ( 33 | auto_pan_padding_bottom_right, 34 | autoPanPaddingBottomRight, 35 | Point 36 | ), 37 | (auto_pan_padding, autoPanPadding, Point), 38 | (keep_in_view, keepInView, bool), 39 | (close_button, closeButton, bool), 40 | (auto_close, autoClose, bool), 41 | (close_on_escape_key, closeOnEscapeKey, bool), 42 | (close_on_click, closeOnClick, bool), 43 | (class_name, className, String) 44 | ); 45 | 46 | impl Default for PopupOptions { 47 | fn default() -> Self { 48 | Self::new() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/raster/image_overlay.rs: -------------------------------------------------------------------------------- 1 | use crate::{create_object_with_properties, LatLngBounds, Layer}; 2 | use js_sys::Object; 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | #[wasm_bindgen(extends = Layer, js_name = ImageOverlay, js_namespace = L)] 8 | #[derive(Debug, Clone)] 9 | pub type ImageOverlay; 10 | 11 | #[wasm_bindgen(constructor, js_namespace = L)] 12 | pub fn new(image_url: &str, bounds: &LatLngBounds) -> ImageOverlay; 13 | 14 | #[wasm_bindgen(constructor, js_namespace = L)] 15 | pub fn new_with_options( 16 | image_url: &str, 17 | bounds: &LatLngBounds, 18 | options: &ImageOverlayOptions, 19 | ) -> ImageOverlay; 20 | } 21 | 22 | create_object_with_properties!( 23 | (ImageOverlayOptions, ImageOverlayOptions), 24 | (opacity, opacity, f64), 25 | (alt, alt, String), 26 | (interactive, interactive, bool), 27 | (cross_origin, crossOrigin, String), 28 | (cross_origin_toggle, crossOrigin, bool), 29 | (error_overlay_url, errorOverlayUrl, String), 30 | (z_index, zIndex, f64), 31 | (class_name, className, String), 32 | // Interactive layer 33 | (bubbling_mouse_events, bubblingMouseEvents, bool), 34 | // Layer options 35 | (pane, pane, String), 36 | (attribution, attribution, String) 37 | ); 38 | 39 | impl Default for ImageOverlayOptions { 40 | fn default() -> Self { 41 | ImageOverlayOptions::new() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/raster/mod.rs: -------------------------------------------------------------------------------- 1 | mod image_overlay; 2 | mod tile_layer; 3 | mod tile_layer_wms; 4 | mod video_overlay; 5 | 6 | pub use image_overlay::{ImageOverlay, ImageOverlayOptions}; 7 | pub use tile_layer::{TileLayer, TileLayerOptions}; 8 | pub use tile_layer_wms::{TileLayerWms, TileLayerWmsOptions, WmsRequestBuilder}; 9 | pub use video_overlay::{VideoOverlay, VideoOverlayOptions}; 10 | -------------------------------------------------------------------------------- /src/raster/tile_layer.rs: -------------------------------------------------------------------------------- 1 | use js_sys::{Function, Object}; 2 | use wasm_bindgen::prelude::*; 3 | use web_sys::HtmlElement; 4 | 5 | use crate::{create_object_with_properties, GridLayer, GridLayerOptions, LatLng}; 6 | 7 | #[wasm_bindgen] 8 | extern "C" { 9 | 10 | #[derive(Debug, Clone, PartialEq)] 11 | #[wasm_bindgen(extends = GridLayer)] 12 | pub type TileLayer; 13 | 14 | #[wasm_bindgen(constructor, js_namespace = L)] 15 | pub fn new(url_template: &str) -> TileLayer; 16 | 17 | #[wasm_bindgen(constructor, js_namespace = L)] 18 | pub fn new_options(url_template: &str, options: &TileLayerOptions) -> TileLayer; 19 | 20 | #[wasm_bindgen(method, js_name = setUrl)] 21 | pub fn set_url(this: &TileLayer, url: &str, no_redraw: Option) -> TileLayer; 22 | 23 | #[wasm_bindgen(method, getter, js_name = _url)] 24 | pub fn url(this: &TileLayer) -> String; 25 | 26 | #[wasm_bindgen(method, js_name = getTileUrl)] 27 | pub fn get_tile_url(this: &TileLayer, coords: &LatLng) -> String; 28 | 29 | #[wasm_bindgen(method, js_name = createTile)] 30 | pub fn create_tile(this: &TileLayer, lat_long: &LatLng) -> HtmlElement; 31 | 32 | #[wasm_bindgen(method, js_name = createTile)] 33 | pub fn create_tile_with_done( 34 | this: &TileLayer, 35 | lat_long: &LatLng, 36 | done: &Function, 37 | ) -> HtmlElement; 38 | } 39 | 40 | create_object_with_properties!( 41 | (TileLayerOptions, TileLayerOptions, GridLayerOptions), 42 | (min_zoom, minZoom, f64), 43 | (max_zoom, maxZoom, f64), 44 | (subdomains, subdomains, bool), 45 | (error_tile_url, errorTileUrl, String), 46 | (zoom_offset, zoomOffset, f64), 47 | (tms, tms, bool), 48 | (zoom_reverse, zoomReverse, bool), 49 | (detect_retina, detectRetina, bool), 50 | (attribution, attribution, String), 51 | (cross_origin, crossOrigin, String), 52 | (referrer_policy, referrerPolicy, String) 53 | ); 54 | 55 | impl Default for TileLayerOptions { 56 | fn default() -> Self { 57 | TileLayerOptions::new() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/raster/tile_layer_wms.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use url::{ParseError, Url}; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use crate::{create_object_with_properties, Crs, LatLng, Map, TileLayer, TileLayerOptions}; 6 | 7 | #[wasm_bindgen] 8 | extern "C" { 9 | 10 | #[derive(Debug, Clone, PartialEq)] 11 | #[wasm_bindgen(extends = TileLayer, js_namespace = ["L", "tileLayer"], js_name = "TileLayerWMS")] 12 | pub type TileLayerWms; 13 | 14 | #[wasm_bindgen(js_namespace = ["L", "tileLayer"], js_name = "wms")] 15 | fn new_wms(url_template: &str) -> TileLayerWms; 16 | 17 | #[wasm_bindgen(js_namespace = ["L", "tileLayer"], js_name = "wms")] 18 | fn new_wms_options(url_template: &str, options: &TileLayerWmsOptions) -> TileLayerWms; 19 | 20 | #[wasm_bindgen(method, js_name = setParams)] 21 | pub fn set_params( 22 | this: &TileLayer, 23 | params: &TileLayerWmsOptions, 24 | no_redraw: Option, 25 | ) -> TileLayerWms; 26 | 27 | } 28 | 29 | impl TileLayerWms { 30 | #[must_use] 31 | pub fn new(url_template: &str) -> TileLayerWms { 32 | new_wms(url_template) 33 | } 34 | 35 | #[must_use] 36 | pub fn new_options(url_template: &str, options: &TileLayerWmsOptions) -> TileLayerWms { 37 | new_wms_options(url_template, options) 38 | } 39 | 40 | #[must_use] 41 | #[allow(clippy::missing_panics_doc)] 42 | pub fn get_params(&self) -> TileLayerWmsOptions { 43 | js_sys::Reflect::get(self.as_ref(), &wasm_bindgen::JsValue::from("wmsParams")) 44 | .expect("Property wmsParams not available.") 45 | .into() 46 | } 47 | } 48 | 49 | create_object_with_properties!( 50 | (TileLayerWmsOptions, TileLayerWmsOptions, TileLayerOptions), 51 | (layers, layers, String), 52 | (styles, styles, String), 53 | (format, format, String), 54 | (transparent, transparent, bool), 55 | (version, version, String), 56 | (crs, crs, Crs), 57 | (uppercase, uppercase, bool) 58 | ); 59 | 60 | impl Default for TileLayerWmsOptions { 61 | fn default() -> Self { 62 | TileLayerWmsOptions::new() 63 | } 64 | } 65 | 66 | create_object_with_properties!( 67 | (WmsRequestParameter, WmsRequestParameter), 68 | (request, request, String), 69 | (service, service, String), 70 | (srs, srs, String), 71 | (styles, styles, String), 72 | (transparent, transparent, bool), 73 | (version, version, String), 74 | (format, format, String), 75 | (bbox, bbox, String), 76 | (height, height, f64), 77 | (width, width, f64), 78 | (layers, layers, String), 79 | (query_layers, query_layers, String), 80 | (info_format, info_format, String), 81 | (x, x, f64), 82 | (y, y, f64), 83 | (i, i, f64), 84 | (j, j, f64) 85 | ); 86 | 87 | /// Construct a request URL for a WMS service. 88 | /// 89 | /// # Defaults 90 | /// The default implementation creates a request with the following adjusted parameters: 91 | /// 92 | /// - Request: `GetFeatureInfo` 93 | /// - Service: `WMS` 94 | /// - SRS: `EPSG:3426` 95 | /// - Info format: `geojson` 96 | pub struct WmsRequestBuilder { 97 | params: WmsRequestParameter, 98 | } 99 | 100 | impl WmsRequestBuilder { 101 | /// Sets the service parameter. 102 | #[must_use] 103 | pub fn with_service(self, service: &str) -> Self { 104 | self.params.set_service(service.to_string()); 105 | self 106 | } 107 | 108 | /// Sets the request parameter. 109 | #[must_use] 110 | pub fn with_request(self, request: &str) -> Self { 111 | self.params.set_request(request.to_string()); 112 | self 113 | } 114 | 115 | /// Sets the srs parameter. 116 | #[must_use] 117 | pub fn with_srs(self, srs: &str) -> Self { 118 | self.params.set_srs(srs.to_string()); 119 | self 120 | } 121 | 122 | /// Sets the info format parameter. 123 | #[must_use] 124 | pub fn with_info_format(self, info_format: &str) -> Self { 125 | self.params.set_info_format(info_format.to_string()); 126 | self 127 | } 128 | 129 | /// Creates the [Url] for the request with the parameters set previously. 130 | pub fn build( 131 | &self, 132 | map: &Map, 133 | layer: &TileLayerWms, 134 | latlng: &LatLng, 135 | ) -> Result { 136 | let wms_params = layer.get_params(); 137 | let map_size = map.get_size(); 138 | let point = map.lat_lng_to_container_point(latlng); 139 | 140 | self.params.set_styles(wms_params.styles()); 141 | self.params.set_transparent(wms_params.transparent()); 142 | self.params.set_version(wms_params.version()); 143 | self.params.set_format(wms_params.format()); 144 | self.params.set_bbox(map.get_bounds().to_bbox_string()); 145 | self.params.set_height(map_size.y()); 146 | self.params.set_width(map_size.x()); 147 | self.params.set_layers(wms_params.layers()); 148 | self.params.set_query_layers(wms_params.layers()); 149 | 150 | let x = point.x().floor(); 151 | let y = point.y().floor(); 152 | 153 | if &wms_params.version()[..] == "1.3.0" { 154 | self.params.set_i(x); 155 | self.params.set_j(y); 156 | } else { 157 | self.params.set_x(x); 158 | self.params.set_y(y); 159 | } 160 | 161 | Url::parse( 162 | &(layer.url() 163 | + &crate::Util::get_param_string_url_uppercase( 164 | self.params.clone().into(), 165 | &layer.url(), 166 | true, 167 | )), 168 | ) 169 | } 170 | } 171 | 172 | impl Default for WmsRequestBuilder { 173 | fn default() -> Self { 174 | let params = WmsRequestParameter::new(); 175 | params.set_request("GetFeatureInfo".to_string()); 176 | params.set_service("WMS".to_string()); 177 | params.set_srs("EPSG:4326".to_string()); 178 | params.set_info_format("geojson".to_string()); 179 | Self { params } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/raster/video_overlay.rs: -------------------------------------------------------------------------------- 1 | use crate::{create_object_with_properties, ImageOverlay, LatLngBounds, Layer}; 2 | use js_sys::Object; 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen] 6 | extern "C" { 7 | #[wasm_bindgen(extends = ImageOverlay, js_name = ImageOverlay, js_namespace = L)] 8 | #[derive(Debug, Clone)] 9 | pub type VideoOverlay; 10 | 11 | #[wasm_bindgen(constructor, js_namespace = L)] 12 | pub fn new(image_url: &str, bounds: &LatLngBounds) -> VideoOverlay; 13 | 14 | #[wasm_bindgen(constructor, js_namespace = L)] 15 | pub fn new_with_options( 16 | image_url: &str, 17 | bounds: &LatLngBounds, 18 | options: &VideoOverlayOptions, 19 | ) -> VideoOverlay; 20 | } 21 | 22 | create_object_with_properties!( 23 | (VideoOverlayOptions, VideoOverlayOptions), 24 | (opacity, opacity, f64), 25 | (alt, alt, String), 26 | (interactive, interactive, bool), 27 | (cross_origin, crossOrigin, String), 28 | (cross_origin_toggle, crossOrigin, bool), 29 | (error_overlay_url, errorOverlayUrl, String), 30 | (z_index, zIndex, f64), 31 | (class_name, className, String), 32 | // Interactive layer 33 | (bubbling_mouse_events, bubblingMouseEvents, bool), 34 | // Layer options 35 | (pane, pane, String), 36 | (attribution, attribution, String), 37 | (autoplay, autoplay, bool), 38 | (looped, loop, bool), 39 | (keep_aspect_ratio, keepAspectRatio, bool), 40 | (muted, muted, bool), 41 | (plays_inline, playsInline, bool) 42 | ); 43 | 44 | impl Default for VideoOverlayOptions { 45 | fn default() -> Self { 46 | VideoOverlayOptions::new() 47 | } 48 | } 49 | 50 | impl From for Layer { 51 | fn from(value: VideoOverlay) -> Self { 52 | value.unchecked_into() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/shapes/circle.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use std::ops::DerefMut; 3 | use wasm_bindgen::prelude::*; 4 | 5 | use crate::evented::{LeafletEventHandler, MouseEvents, MoveEvents, PopupEvents, TooltipEvents}; 6 | use crate::{ 7 | create_object_with_properties, CircleMarker, Evented, LatLng, LatLngBounds, Layer, LayerEvents, 8 | PathOptions, 9 | }; 10 | 11 | #[wasm_bindgen] 12 | extern "C" { 13 | /// [`Circle`](https://leafletjs.com/reference.html#circle) 14 | #[derive(Debug, Clone)] 15 | #[wasm_bindgen(extends = CircleMarker)] 16 | pub type Circle; 17 | 18 | #[wasm_bindgen(constructor, js_namespace = L)] 19 | pub fn new(latlng: &LatLng) -> Circle; 20 | 21 | #[wasm_bindgen(constructor, js_namespace = L)] 22 | pub fn new_with_radius(latlng: &LatLng, radius: f64) -> Circle; 23 | 24 | #[wasm_bindgen(constructor, js_namespace = L)] 25 | pub fn new_with_options(latlng: &LatLng, options: &CircleOptions) -> Circle; 26 | 27 | #[wasm_bindgen(method, js_name = setStyle)] 28 | pub fn set_style(this: &Circle, options: &CircleOptions) -> Circle; 29 | 30 | /// [`setRadius`](https://leafletjs.com/reference-1.7.1.html#circle-setradius) 31 | #[wasm_bindgen(method, js_name = setRadius)] 32 | pub fn set_radius(this: &Circle, radius: f64); 33 | 34 | /// [`getRadius`](https://leafletjs.com/reference-1.7.1.html#circle-getradius) 35 | #[wasm_bindgen(method, js_name = getRadius)] 36 | pub fn get_radius(this: &Circle) -> f64; 37 | 38 | /// [`getBounds`](https://leafletjs.com/reference.html#circle-getbounds) 39 | #[wasm_bindgen(method, js_name = getBounds)] 40 | pub fn get_bounds(this: &Circle) -> LatLngBounds; 41 | } 42 | 43 | create_object_with_properties!( 44 | (CircleOptions, CircleOptions, PathOptions), 45 | (radius, radius, f64) 46 | ); 47 | 48 | impl Default for CircleOptions { 49 | fn default() -> Self { 50 | Self::new() 51 | } 52 | } 53 | 54 | impl DerefMut for CircleOptions { 55 | fn deref_mut(&mut self) -> &mut Self::Target { 56 | &mut self.obj 57 | } 58 | } 59 | 60 | impl From for Layer { 61 | fn from(circle: Circle) -> Self { 62 | circle.unchecked_into() 63 | } 64 | } 65 | 66 | impl LeafletEventHandler for Circle { 67 | fn on(&self, event: &str, callback: &JsValue) { 68 | self.unchecked_ref::().on(event, callback); 69 | } 70 | } 71 | 72 | impl MoveEvents for Circle {} 73 | impl MouseEvents for Circle {} 74 | impl LayerEvents for Circle {} 75 | impl PopupEvents for Circle {} 76 | impl TooltipEvents for Circle {} 77 | -------------------------------------------------------------------------------- /src/shapes/circle_marker.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | use crate::evented::{LeafletEventHandler, MouseEvents, MoveEvents, PopupEvents, TooltipEvents}; 4 | use crate::{Evented, LatLng, LayerEvents, Path}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | // CircleMarker 9 | 10 | /// [`CircleMarker`](https://leafletjs.com/reference-1.7.1.html#circlemarker) 11 | #[derive(Debug, Clone)] 12 | #[wasm_bindgen(extends = Path)] 13 | pub type CircleMarker; 14 | 15 | /// [`Constructor`](https://leafletjs.com/reference-1.7.1.html#circlemarker-l-circlemarker) 16 | #[wasm_bindgen(constructor, js_namespace = L)] 17 | pub fn new(latlng: &LatLng) -> CircleMarker; 18 | 19 | /// [`Constructor`](https://leafletjs.com/reference-1.7.1.html#circlemarker-l-circlemarker) 20 | #[wasm_bindgen(constructor, js_namespace = L)] 21 | pub fn new_with_options(latlng: &LatLng, options: &JsValue) -> CircleMarker; 22 | 23 | /// [`toGeoJSON`](https://leafletjs.com/reference-1.7.1.html#circlemarker-togeojson) 24 | #[wasm_bindgen(method, js_name = toGeoJSON)] 25 | pub fn to_geo_json(this: &CircleMarker) -> JsValue; 26 | 27 | /// [`setLatLng`](https://leafletjs.com/reference-1.7.1.html#circlemarker-setlanglng) 28 | #[wasm_bindgen(method, js_name = setLatLng)] 29 | pub fn set_lat_lng(this: &CircleMarker, latlng: &LatLng); 30 | 31 | /// [`getLatLng`](https://leafletjs.com/reference-1.7.1.html#circlemarker-getlatlng) 32 | #[wasm_bindgen(method, js_name = getLatLng)] 33 | pub fn get_lat_lng(this: &CircleMarker) -> LatLng; 34 | 35 | /// [`setRadius`](https://leafletjs.com/reference-1.7.1.html#circlemarker-setradius) 36 | #[wasm_bindgen(method, js_name = setRadius)] 37 | pub fn set_radius(this: &CircleMarker, radius: f64); 38 | 39 | /// [`getRadius`](https://leafletjs.com/reference-1.7.1.html#circlemarker-getradius) 40 | #[wasm_bindgen(method, js_name = getRadius)] 41 | pub fn get_radius(this: &CircleMarker) -> f64; 42 | 43 | } 44 | 45 | impl LeafletEventHandler for CircleMarker { 46 | fn on(&self, event: &str, callback: &JsValue) { 47 | self.unchecked_ref::().on(event, callback); 48 | } 49 | } 50 | 51 | impl MoveEvents for CircleMarker {} 52 | impl MouseEvents for CircleMarker {} 53 | impl LayerEvents for CircleMarker {} 54 | impl PopupEvents for CircleMarker {} 55 | impl TooltipEvents for CircleMarker {} 56 | -------------------------------------------------------------------------------- /src/shapes/mod.rs: -------------------------------------------------------------------------------- 1 | mod circle; 2 | mod circle_marker; 3 | mod path; 4 | mod polygon; 5 | mod polyline; 6 | mod rectangle; 7 | 8 | pub use circle::{Circle, CircleOptions}; 9 | pub use circle_marker::CircleMarker; 10 | pub use path::{Path, PathOptions}; 11 | pub use polygon::Polygon; 12 | pub use polyline::{Polyline, PolylineOptions}; 13 | pub use rectangle::Rectangle; 14 | -------------------------------------------------------------------------------- /src/shapes/path.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::{create_object_with_properties, Layer}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | /// [`Path`](https://leafletjs.com/reference.html#path) 9 | #[wasm_bindgen(extends = Layer)] 10 | #[derive(Debug, Clone)] 11 | pub type Path; 12 | 13 | /// [`redraw`](https://leafletjs.com/reference.html#path-redraw) 14 | #[wasm_bindgen(method)] 15 | pub fn redraw(this: &Path); 16 | 17 | /// [`setStyle`](https://leafletjs.com/reference.html#path-setstyle) 18 | #[wasm_bindgen(method, js_name = setStyle)] 19 | pub fn set_style(this: &Path, path_options: &PathOptions); 20 | 21 | /// [`bringToFront`](https://leafletjs.com/reference.html#path-bringtofront) 22 | #[wasm_bindgen(method, js_name = bringToFront)] 23 | pub fn bring_to_front(this: &Path); 24 | 25 | /// [`bringToBack`](https://leafletjs.com/reference.html#path-bringtoback) 26 | #[wasm_bindgen(method, js_name = bringToBack)] 27 | pub fn bring_to_back(this: &Path); 28 | } 29 | 30 | create_object_with_properties!( 31 | (PathOptions, PathOptions), 32 | (stroke, stroke, bool), 33 | (color, color, String), 34 | (weight, weight, f64), 35 | (interactive, interactive, bool), 36 | (opacity, opacity, f64), 37 | (line_cap, lineCap, String), 38 | (line_join, lineJoin, String), 39 | (dash_array, dashArray, String), 40 | (dash_offset, dashOffset, String), 41 | (fill, fill, bool), 42 | (fill_color, fillColor, String), 43 | (fill_opacity, fillOpacity, f64), 44 | (fill_rule, fillRule, String), 45 | (bubbling_mouse_events, bubblingMouseEvents, bool), 46 | (renderer, renderer, JsValue), 47 | (class_name, className, String) 48 | ); 49 | 50 | impl Default for PathOptions { 51 | fn default() -> Self { 52 | PathOptions::new() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/shapes/polygon.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Array; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::evented::{LeafletEventHandler, MouseEvents, PopupEvents, TooltipEvents}; 5 | use crate::{Evented, LatLng, Layer, LayerEvents, Polyline, PolylineOptions}; 6 | 7 | #[wasm_bindgen] 8 | extern "C" { 9 | #[derive(Debug, Clone)] 10 | #[wasm_bindgen(extends = Polyline)] 11 | pub type Polygon; 12 | 13 | #[wasm_bindgen(constructor, js_namespace = L)] 14 | pub fn new(latlngs: &Array) -> Polygon; 15 | 16 | #[wasm_bindgen(constructor, js_namespace = L)] 17 | pub fn new_with_options(latlngs: &Array, options: &PolylineOptions) -> Polygon; 18 | 19 | #[wasm_bindgen(method, js_name = getCenter)] 20 | pub fn get_center(this: &Polygon) -> LatLng; 21 | } 22 | 23 | /// Seems that wasmbindgen doesn't implement From for Layer 24 | impl From for Layer { 25 | fn from(value: Polygon) -> Self { 26 | value.unchecked_into() 27 | } 28 | } 29 | 30 | impl LeafletEventHandler for Polygon { 31 | fn on(&self, event: &str, callback: &JsValue) { 32 | self.unchecked_ref::().on(event, callback); 33 | } 34 | } 35 | 36 | impl MouseEvents for Polygon {} 37 | impl LayerEvents for Polygon {} 38 | impl PopupEvents for Polygon {} 39 | impl TooltipEvents for Polygon {} 40 | -------------------------------------------------------------------------------- /src/shapes/polyline.rs: -------------------------------------------------------------------------------- 1 | use std::ops::DerefMut; 2 | 3 | use js_sys::{Array, Object}; 4 | use wasm_bindgen::prelude::*; 5 | 6 | use crate::evented::{LeafletEventHandler, MouseEvents, PopupEvents, TooltipEvents}; 7 | use crate::{ 8 | create_object_with_properties, Evented, LatLng, LatLngBounds, Layer, LayerEvents, Path, 9 | PathOptions, Point, 10 | }; 11 | 12 | #[wasm_bindgen] 13 | extern "C" { 14 | #[wasm_bindgen(extends = Path)] 15 | #[derive(Debug, Clone)] 16 | pub type Polyline; 17 | 18 | #[wasm_bindgen(constructor, js_namespace = L)] 19 | pub fn new(latlngs: &Array) -> Polyline; 20 | 21 | #[wasm_bindgen(constructor, js_namespace = L)] 22 | pub fn new_with_options(latlngs: &Array, options: &PolylineOptions) -> Polyline; 23 | 24 | #[wasm_bindgen(method, js_name = toGeoJSON)] 25 | pub fn to_geo_json(this: &Polyline, precision: f64) -> Object; 26 | 27 | #[wasm_bindgen(method, js_name = getLatLngs)] 28 | pub fn get_lat_lngs(this: &Polyline) -> Array; 29 | 30 | #[wasm_bindgen(method, js_name = setLatLngs)] 31 | pub fn set_lat_lngs(this: &Polyline, lat_lngs: &Array) -> Polyline; 32 | 33 | #[wasm_bindgen(method, js_name = isEmpty)] 34 | pub fn is_empty(this: &Polyline) -> bool; 35 | 36 | #[wasm_bindgen(method, js_name = closestLayerPoint)] 37 | pub fn closest_layer_point(this: &Polyline, point: &Point) -> Point; 38 | 39 | #[wasm_bindgen(method, js_name = getCenter)] 40 | pub fn get_center(this: &Polyline) -> LatLng; 41 | 42 | #[wasm_bindgen(method, js_name = getBounds)] 43 | pub fn get_bounds(this: &Polyline) -> LatLngBounds; 44 | 45 | #[wasm_bindgen(method,js_name = addLatLng)] 46 | pub fn add_lat_lng(this: &Polyline, lat_lng: &LatLng) -> Polyline; 47 | } 48 | 49 | create_object_with_properties!( 50 | (PolylineOptions, PolylineOptions, PathOptions), 51 | (smooth_factor, smoothFactor, f64), 52 | (no_clip, noClip, bool) 53 | ); 54 | 55 | impl Default for PolylineOptions { 56 | fn default() -> Self { 57 | Self::new() 58 | } 59 | } 60 | 61 | /// Seems that wasmbindgen doesn't implement From for Layer 62 | impl From for Layer { 63 | fn from(value: Polyline) -> Self { 64 | value.unchecked_into() 65 | } 66 | } 67 | 68 | impl DerefMut for PolylineOptions { 69 | fn deref_mut(&mut self) -> &mut Self::Target { 70 | &mut self.obj 71 | } 72 | } 73 | 74 | impl LeafletEventHandler for Polyline { 75 | fn on(&self, event: &str, callback: &JsValue) { 76 | self.unchecked_ref::().on(event, callback); 77 | } 78 | } 79 | 80 | impl MouseEvents for Polyline {} 81 | impl LayerEvents for Polyline {} 82 | impl PopupEvents for Polyline {} 83 | impl TooltipEvents for Polyline {} 84 | -------------------------------------------------------------------------------- /src/shapes/rectangle.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | use crate::evented::{LeafletEventHandler, MouseEvents, PopupEvents, TooltipEvents}; 4 | use crate::{Evented, LatLngBounds, LayerEvents, Polygon, PolylineOptions}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | // Rectangle 9 | 10 | #[derive(Debug)] 11 | #[wasm_bindgen(extends = Polygon)] 12 | pub type Rectangle; 13 | 14 | #[wasm_bindgen(constructor, js_namespace = L)] 15 | pub fn new(bounds: &LatLngBounds) -> Rectangle; 16 | 17 | #[wasm_bindgen(constructor, js_namespace = L)] 18 | pub fn new_with_options(bounds: &LatLngBounds, options: &PolylineOptions) -> Rectangle; 19 | 20 | #[wasm_bindgen(method, js_name = setBounds)] 21 | pub fn set_bounds(this: &Rectangle, bounds: &LatLngBounds) -> Rectangle; 22 | } 23 | 24 | impl LeafletEventHandler for Rectangle { 25 | fn on(&self, event: &str, callback: &JsValue) { 26 | self.unchecked_ref::().on(event, callback); 27 | } 28 | } 29 | 30 | impl MouseEvents for Rectangle {} 31 | impl LayerEvents for Rectangle {} 32 | impl PopupEvents for Rectangle {} 33 | impl TooltipEvents for Rectangle {} 34 | -------------------------------------------------------------------------------- /src/tooltip.rs: -------------------------------------------------------------------------------- 1 | use js_sys::Object; 2 | use wasm_bindgen::prelude::*; 3 | 4 | use crate::{create_object_with_properties, DivOverlay, LatLng, Layer, Point}; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | /// [`Tooltip`](https://leafletjs.com/reference-1.7.1.html#tooltip) 9 | #[derive(Debug, Clone)] 10 | #[wasm_bindgen(extends = DivOverlay)] 11 | pub type Tooltip; 12 | 13 | /// [`L.tooltip`](https://leafletjs.com/reference-1.7.1.html#tooltip-l-tooltip) 14 | #[wasm_bindgen(js_namespace = L, constructor, js_name = Tooltip)] 15 | pub fn new(options: &TooltipOptions, layer: Option<&Layer>) -> Tooltip; 16 | 17 | #[wasm_bindgen(constructor, js_namespace = L)] 18 | pub fn new_with_lat_lng(lat_lng: &LatLng, options: &TooltipOptions) -> Tooltip; 19 | 20 | #[wasm_bindgen(method, js_name = setContent)] 21 | pub fn set_content(this: &Tooltip, content: &JsValue) -> Tooltip; 22 | 23 | #[wasm_bindgen(method, js_name = getContent)] 24 | pub fn get_content(this: &Tooltip) -> JsValue; 25 | 26 | #[wasm_bindgen(method, js_name = setLatLng)] 27 | pub fn set_lat_lng(this: &Tooltip, latlng: &JsValue) -> Tooltip; 28 | 29 | #[wasm_bindgen(method, js_name = getLatLng)] 30 | pub fn get_lat_lng(this: &Tooltip) -> LatLng; 31 | } 32 | 33 | create_object_with_properties!( 34 | (TooltipOptions, TooltipOptions), 35 | (pane, pane, String), 36 | (direction, direction, String), 37 | (offset, offset, Point), 38 | (permanent, permanent, bool), 39 | (sticky, sticky, bool), 40 | (opacity, opacity, f64) 41 | ); 42 | 43 | impl Default for TooltipOptions { 44 | fn default() -> Self { 45 | Self::new() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | //! L.Util bindings. 2 | 3 | use js_sys::Object; 4 | use wasm_bindgen::prelude::*; 5 | 6 | #[wasm_bindgen] 7 | extern "C" { 8 | #[wasm_bindgen(js_namespace = ["L", "Util"], js_name = "getParamString")] 9 | fn get_param_string(params: Object) -> String; 10 | 11 | #[wasm_bindgen(js_namespace = ["L", "Util"], js_name = "getParamString")] 12 | fn get_param_string_url(params: Object, url: &str) -> String; 13 | 14 | #[wasm_bindgen(js_namespace = ["L", "Util"], js_name = "getParamString")] 15 | fn get_param_string_url_uppercase(params: Object, url: &str, uppercase: bool) -> String; 16 | } 17 | 18 | /// The `L.Util` namespace. 19 | pub struct Util; 20 | 21 | impl Util { 22 | /// [`getParamString`](https://leafletjs.com/reference.html#util-getparamstring). 23 | #[must_use] 24 | pub fn get_param_string(params: Object) -> String { 25 | get_param_string(params) 26 | } 27 | /// [`getParamString`](https://leafletjs.com/reference.html#util-getparamstring). 28 | #[must_use] 29 | pub fn get_param_string_url(params: Object, url: &str) -> String { 30 | get_param_string_url(params, url) 31 | } 32 | /// [`getParamString`](https://leafletjs.com/reference.html#util-getparamstring). 33 | #[must_use] 34 | pub fn get_param_string_url_uppercase(params: Object, url: &str, uppercase: bool) -> String { 35 | get_param_string_url_uppercase(params, url, uppercase) 36 | } 37 | } 38 | --------------------------------------------------------------------------------