Commit 43370abfea7cd24e86ea747adf23c021031c24dc
1 parent
53f01ecc34
Exists in
master
and in
1 other branch
clear map canvas when importing new data set
Showing 2 changed files with 7 additions and 3 deletions Inline Diff
src/main/kotlin/map/CircleMarkerGenerator.kt
View file @
43370ab
| package map | 1 | 1 | package map | |
| 2 | 2 | |||
| import application.model.observableMessages | 3 | 3 | import application.model.observableMessages | |
| 4 | 4 | |||
| fun clearMap(map: LeafletMapView) { | 5 | 5 | fun clearMapCanvas(map: LeafletMapView) { | |
| map.clearAllLayer() | 6 | 6 | map.execScript(""" | |
| 7 | |myRenderer.removeFrom(myMap) | |||
| 8 | |var myRenderer = L.canvas({ padding: 0.5 }); | |||
| 9 | """.trimMargin()) | |||
| } | 7 | 10 | } | |
| 8 | 11 | |||
| fun displayMessageOnMap(map: LeafletMapView) { | 9 | 12 | fun displayMessageOnMap(map: LeafletMapView) { | |
| 13 | clearMapCanvas(map) | |||
| observableMessages.vessels.forEach { (_, value) -> | 10 | 14 | observableMessages.vessels.forEach { (_, value) -> | |
| value.messages.forEach { (_, message) -> | 11 | 15 | value.messages.forEach { (_, message) -> | |
| map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01}).addTo(myMap)") | 12 | 16 | map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01}).addTo(myMap)") | |
| } | 13 | 17 | } | |
| } | 14 | 18 | } |
src/main/kotlin/map/LeafletMapView.kt
View file @
43370ab
| package map | 1 | 1 | package map | |
| 2 | 2 | |||
| import javafx.concurrent.Worker | 3 | 3 | import javafx.concurrent.Worker | |
| import javafx.scene.layout.StackPane | 4 | 4 | import javafx.scene.layout.StackPane | |
| import javafx.scene.paint.Color | 5 | 5 | import javafx.scene.paint.Color | |
| import javafx.scene.shape.Polygon | 6 | 6 | import javafx.scene.shape.Polygon | |
| import javafx.scene.web.WebEngine | 7 | 7 | import javafx.scene.web.WebEngine | |
| import javafx.scene.web.WebView | 8 | 8 | import javafx.scene.web.WebView | |
| import map.events.* | 9 | 9 | import map.events.* | |
| import netscape.javascript.JSObject | 10 | 10 | import netscape.javascript.JSObject | |
| import java.io.ByteArrayOutputStream | 11 | 11 | import java.io.ByteArrayOutputStream | |
| import java.io.File | 12 | 12 | import java.io.File | |
| import java.io.IOException | 13 | 13 | import java.io.IOException | |
| import java.net.URL | 14 | 14 | import java.net.URL | |
| import java.util.* | 15 | 15 | import java.util.* | |
| import java.util.concurrent.CompletableFuture | 16 | 16 | import java.util.concurrent.CompletableFuture | |
| import javax.imageio.ImageIO | 17 | 17 | import javax.imageio.ImageIO | |
| 18 | 18 | |||
| 19 | 19 | |||
| /** | 20 | 20 | /** | |
| * JavaFX component for displaying OpenStreetMap based maps by using the Leaflet.js JavaScript library inside a WebView | 21 | 21 | * JavaFX component for displaying OpenStreetMap based maps by using the Leaflet.js JavaScript library inside a WebView | |
| * browser component.<br/> | 22 | 22 | * browser component.<br/> | |
| * This component can be embedded most easily by placing it inside a StackPane, the component uses then the size of the | 23 | 23 | * This component can be embedded most easily by placing it inside a StackPane, the component uses then the size of the | |
| * parent automatically. | 24 | 24 | * parent automatically. | |
| * | 25 | 25 | * | |
| * @author Stefan Saring | 26 | 26 | * @author Stefan Saring | |
| * @author Niklas Kellner | 27 | 27 | * @author Niklas Kellner | |
| */ | 28 | 28 | */ | |
| class LeafletMapView : StackPane() { | 29 | 29 | class LeafletMapView : StackPane() { | |
| 30 | 30 | |||
| private val webView = WebView() | 31 | 31 | private val webView = WebView() | |
| private val webEngine: WebEngine = webView.engine | 32 | 32 | private val webEngine: WebEngine = webView.engine | |
| 33 | 33 | |||
| private var varNameSuffix: Int = 1 | 34 | 34 | private var varNameSuffix: Int = 1 | |
| private val mapClickEvent = MapClickEventMaker() | 35 | 35 | private val mapClickEvent = MapClickEventMaker() | |
| private val markerClickEvent = MarkerClickEventMaker() | 36 | 36 | private val markerClickEvent = MarkerClickEventMaker() | |
| private val mapMoveEvent = MapMoveEventMaker() | 37 | 37 | private val mapMoveEvent = MapMoveEventMaker() | |
| internal val zoomLimitSmallMarker = 8 | 38 | 38 | internal val zoomLimitSmallMarker = 8 | |
| 39 | 39 | |||
| /** | 40 | 40 | /** | |
| * Creates the LeafletMapView component, it does not show any map yet. | 41 | 41 | * Creates the LeafletMapView component, it does not show any map yet. | |
| */ | 42 | 42 | */ | |
| init { | 43 | 43 | init { | |
| this.children.add(webView) | 44 | 44 | this.children.add(webView) | |
| } | 45 | 45 | } | |
| 46 | 46 | |||
| /** | 47 | 47 | /** | |
| * Displays the initial map in the web view. Needs to be called and complete before adding any markers or tracks. | 48 | 48 | * Displays the initial map in the web view. Needs to be called and complete before adding any markers or tracks. | |
| * The returned CompletableFuture will provide the final map load state, the map can be used when the load has | 49 | 49 | * The returned CompletableFuture will provide the final map load state, the map can be used when the load has | |
| * completed with state SUCCEEDED (use CompletableFuture#whenComplete() for waiting to complete). | 50 | 50 | * completed with state SUCCEEDED (use CompletableFuture#whenComplete() for waiting to complete). | |
| * | 51 | 51 | * | |
| * @param mapConfig configuration of the map layers and controls | 52 | 52 | * @param mapConfig configuration of the map layers and controls | |
| * @return the CompletableFuture which will provide the final map load state | 53 | 53 | * @return the CompletableFuture which will provide the final map load state | |
| */ | 54 | 54 | */ | |
| fun displayMap(mapConfig: MapConfig): CompletableFuture<Worker.State> { | 55 | 55 | fun displayMap(mapConfig: MapConfig): CompletableFuture<Worker.State> { | |
| val finalMapLoadState = CompletableFuture<Worker.State>() | 56 | 56 | val finalMapLoadState = CompletableFuture<Worker.State>() | |
| 57 | 57 | |||
| webEngine.loadWorker.stateProperty().addListener { _, _, newValue -> | 58 | 58 | webEngine.loadWorker.stateProperty().addListener { _, _, newValue -> | |
| 59 | 59 | |||
| if (newValue == Worker.State.SUCCEEDED) { | 60 | 60 | if (newValue == Worker.State.SUCCEEDED) { | |
| executeMapSetupScripts(mapConfig) | 61 | 61 | executeMapSetupScripts(mapConfig) | |
| } | 62 | 62 | } | |
| 63 | 63 | |||
| if (newValue == Worker.State.SUCCEEDED || newValue == Worker.State.FAILED) { | 64 | 64 | if (newValue == Worker.State.SUCCEEDED || newValue == Worker.State.FAILED) { | |
| finalMapLoadState.complete(newValue) | 65 | 65 | finalMapLoadState.complete(newValue) | |
| } | 66 | 66 | } | |
| } | 67 | 67 | } | |
| 68 | 68 | |||
| val localFileUrl: URL = LeafletMapView::class.java.getResource("/leafletmap/leafletmap.html") | 69 | 69 | val localFileUrl: URL = LeafletMapView::class.java.getResource("/leafletmap/leafletmap.html") | |
| webEngine.load(localFileUrl.toExternalForm()) | 70 | 70 | webEngine.load(localFileUrl.toExternalForm()) | |
| return finalMapLoadState | 71 | 71 | return finalMapLoadState | |
| } | 72 | 72 | } | |
| 73 | 73 | |||
| private fun executeMapSetupScripts(mapConfig: MapConfig) { | 74 | 74 | private fun executeMapSetupScripts(mapConfig: MapConfig) { | |
| 75 | 75 | |||
| // execute scripts for layer definition | 76 | 76 | // execute scripts for layer definition | |
| mapConfig.layers.forEachIndexed { i, layer -> | 77 | 77 | mapConfig.layers.forEachIndexed { i, layer -> | |
| execScript("var layer${i + 1} = ${layer.javaScriptCode};") | 78 | 78 | execScript("var layer${i + 1} = ${layer.javaScriptCode};") | |
| } | 79 | 79 | } | |
| 80 | 80 | |||
| val jsLayers = mapConfig.layers | 81 | 81 | val jsLayers = mapConfig.layers | |
| .mapIndexed { i, layer -> "'${layer.displayName}': layer${i + 1}" } | 82 | 82 | .mapIndexed { i, layer -> "'${layer.displayName}': layer${i + 1}" } | |
| .joinToString(", ") | 83 | 83 | .joinToString(", ") | |
| execScript("var baseMaps = { $jsLayers };") | 84 | 84 | execScript("var baseMaps = { $jsLayers };") | |
| 85 | 85 | |||
| // execute script for map view creation (Leaflet attribution must not be a clickable link) | 86 | 86 | // execute script for map view creation (Leaflet attribution must not be a clickable link) | |
| execScript( | 87 | 87 | execScript( | |
| """ | 88 | 88 | """ | |
| |var myMap = L.map('map', { | 89 | 89 | |var myMap = L.map('map', { | |
| | center: new L.LatLng(${mapConfig.initialCenter.latitude}, ${mapConfig.initialCenter.longitude}), | 90 | 90 | | center: new L.LatLng(${mapConfig.initialCenter.latitude}, ${mapConfig.initialCenter.longitude}), | |
| | zoom: 5, | 91 | 91 | | zoom: 5, | |
| | zoomControl: false, | 92 | 92 | | zoomControl: false, | |
| | layers: [layer1] | 93 | 93 | | layers: [layer1] | |
| |}); | 94 | 94 | |}); | |
| |L.control.scale().addTo(mymap); | 95 | 95 | |L.control.scale().addTo(myMap); | |
| |var myRenderer = L.canvas({ padding: 0.5 });""".trimMargin() | 96 | 96 | |var myRenderer = L.canvas({ padding: 0.5 });""".trimMargin() | |
| ) | 97 | 97 | ) | |
| 98 | 98 | |||
| // eventZoomChangeIcon() | 99 | 99 | // eventZoomChangeIcon() | |
| 100 | 100 | |||
| // execute script for layer control definition if there are multiple layers | 101 | 101 | // execute script for layer control definition if there are multiple layers | |
| if (mapConfig.layers.size > 1) { | 102 | 102 | if (mapConfig.layers.size > 1) { | |
| execScript( | 103 | 103 | execScript( | |
| """ | 104 | 104 | """ | |
| |var overlayMaps = {}; | 105 | 105 | |var overlayMaps = {}; | |
| |L.control.layers(baseMaps, overlayMaps).addTo(myMap);""".trimMargin() | 106 | 106 | |L.control.layers(baseMaps, overlayMaps).addTo(myMap);""".trimMargin() | |
| ) | 107 | 107 | ) | |
| 108 | 108 | |||
| } | 109 | 109 | } | |
| 110 | 110 | |||
| // execute script for scale control definition | 111 | 111 | // execute script for scale control definition | |
| if (mapConfig.scaleControlConfig.show) { | 112 | 112 | if (mapConfig.scaleControlConfig.show) { | |
| execScript( | 113 | 113 | execScript( | |
| "L.control.scale({position: '${mapConfig.scaleControlConfig.position.positionName}', " + | 114 | 114 | "L.control.scale({position: '${mapConfig.scaleControlConfig.position.positionName}', " + | |
| "metric: ${mapConfig.scaleControlConfig.metric}, " + | 115 | 115 | "metric: ${mapConfig.scaleControlConfig.metric}, " + | |
| "imperial: ${!mapConfig.scaleControlConfig.metric}})" + | 116 | 116 | "imperial: ${!mapConfig.scaleControlConfig.metric}})" + | |
| ".addTo(myMap);" | 117 | 117 | ".addTo(myMap);" | |
| ) | 118 | 118 | ) | |
| } | 119 | 119 | } | |
| 120 | 120 | |||
| // execute script for zoom control definition | 121 | 121 | // execute script for zoom control definition | |
| if (mapConfig.zoomControlConfig.show) { | 122 | 122 | if (mapConfig.zoomControlConfig.show) { | |
| execScript( | 123 | 123 | execScript( | |
| "L.control.zoom({position: '${mapConfig.zoomControlConfig.position.positionName}'})" + | 124 | 124 | "L.control.zoom({position: '${mapConfig.zoomControlConfig.position.positionName}'})" + | |
| ".addTo(myMap);" | 125 | 125 | ".addTo(myMap);" | |
| ) | 126 | 126 | ) | |
| } | 127 | 127 | } | |
| } | 128 | 128 | } | |
| 129 | 129 | |||
| /** | 130 | 130 | /** | |
| * Sets the view of the map to the specified geographical center position and zoom level. | 131 | 131 | * Sets the view of the map to the specified geographical center position and zoom level. | |
| * | 132 | 132 | * | |
| * @param position map center position | 133 | 133 | * @param position map center position | |
| * @param zoomLevel zoom level (0 - 19 for OpenStreetMap) | 134 | 134 | * @param zoomLevel zoom level (0 - 19 for OpenStreetMap) | |
| */ | 135 | 135 | */ | |
| fun setView(position: LatLong, zoomLevel: Int) = | 136 | 136 | fun setView(position: LatLong, zoomLevel: Int) = | |
| execScript("myMap.setView([${position.latitude}, ${position.longitude}], $zoomLevel);") | 137 | 137 | execScript("myMap.setView([${position.latitude}, ${position.longitude}], $zoomLevel);") | |
| 138 | 138 | |||
| /** | 139 | 139 | /** | |
| * Pans the map to the specified geographical center position. | 140 | 140 | * Pans the map to the specified geographical center position. | |
| * | 141 | 141 | * | |
| * @param position map center position | 142 | 142 | * @param position map center position | |
| */ | 143 | 143 | */ | |
| fun panTo(position: LatLong) = | 144 | 144 | fun panTo(position: LatLong) = | |
| execScript("myMap.panTo([${position.latitude}, ${position.longitude}]);") | 145 | 145 | execScript("myMap.panTo([${position.latitude}, ${position.longitude}]);") | |
| 146 | 146 | |||
| /** | 147 | 147 | /** | |
| * Sets the zoom of the map to the specified level. | 148 | 148 | * Sets the zoom of the map to the specified level. | |
| * | 149 | 149 | * | |
| * @param zoomLevel zoom level (0 - 19 for OpenStreetMap) | 150 | 150 | * @param zoomLevel zoom level (0 - 19 for OpenStreetMap) | |
| */ | 151 | 151 | */ | |
| fun setZoom(zoomLevel: Int) = | 152 | 152 | fun setZoom(zoomLevel: Int) = | |
| execScript("myMap.setZoom([$zoomLevel]);") | 153 | 153 | execScript("myMap.setZoom([$zoomLevel]);") | |
| 154 | 154 | |||
| /** | 155 | 155 | /** | |
| * Adds a Marker Object to a map | 156 | 156 | * Adds a Marker Object to a map | |
| * | 157 | 157 | * | |
| * @param marker the Marker Object | 158 | 158 | * @param marker the Marker Object | |
| */ | 159 | 159 | */ | |
| fun addMarker(marker: Marker) { | 160 | 160 | fun addMarker(marker: Marker) { | |
| marker.addToMap(getNextMarkerName(), this) | 161 | 161 | marker.addToMap(getNextMarkerName(), this) | |
| } | 162 | 162 | } | |
| 163 | 163 | |||
| fun addCircle(circle: Circle) { | 164 | 164 | fun addCircle(circle: Circle) { | |
| circle.addToMap(this) | 165 | 165 | circle.addToMap(this) | |
| } | 166 | 166 | } | |
| 167 | 167 | |||
| fun addZone(zone: Zone) { | 168 | 168 | fun addZone(zone: Zone) { | |
| zone.addToMap(this) | 169 | 169 | zone.addToMap(this) | |
| } | 170 | 170 | } | |
| 171 | 171 | |||
| /** | 172 | 172 | /** | |
| * Removes an existing marker from the map | 173 | 173 | * Removes an existing marker from the map | |
| * | 174 | 174 | * | |
| * @param marker the Marker object | 175 | 175 | * @param marker the Marker object | |
| */ | 176 | 176 | */ | |
| fun removeMarker(marker: Marker) { | 177 | 177 | fun removeMarker(marker: Marker) { | |
| execScript("myMap.removeLayer(${marker.getName()});") | 178 | 178 | execScript("myMap.removeLayer(${marker.getName()});") | |
| } | 179 | 179 | } | |
| 180 | 180 | |||
| fun removeCircle(circle: Circle) { | 181 | 181 | fun removeCircle(circle: Circle) { | |
| circle.removeCircle(this) | 182 | 182 | circle.removeCircle(this) | |
| } | 183 | 183 | } | |
| 184 | 184 | |||
| fun removeZone(zone: Zone) { | 185 | 185 | fun removeZone(zone: Zone) { | |
| zone.removeZone() | 186 | 186 | zone.removeZone() | |
| } | 187 | 187 | } | |
| 188 | 188 | |||
| fun removeZone(id: String) { | 189 | 189 | fun removeZone(id: String) { | |
| val idSanitized = id.replace("-", "") | 190 | 190 | val idSanitized = id.replace("-", "") | |
| execScript("myMap.removeLayer(polygon$idSanitized);") | 191 | 191 | execScript("myMap.removeLayer(polygon$idSanitized);") | |
| } | 192 | 192 | } | |
| 193 | 193 | |||
| 194 | 194 | |||
| fun uppdateCircle(circle: Circle, latLong: LatLong, radius: Double) { | 195 | 195 | fun uppdateCircle(circle: Circle, latLong: LatLong, radius: Double) { | |
| circle.modifyCircle(latLong, radius) | 196 | 196 | circle.modifyCircle(latLong, radius) | |
| circle.uppdateMap() | 197 | 197 | circle.uppdateMap() | |
| } | 198 | 198 | } | |
| 199 | 199 | |||
| fun setEventMousePosition() { | 200 | 200 | fun setEventMousePosition() { | |
| execScript( | 201 | 201 | execScript( | |
| "var lat=0.0, lng=0.0;\n" + | 202 | 202 | "var lat=0.0, lng=0.0;\n" + | |
| "myMap.addEventListener('mousemove', function(ev) {\n" + | 203 | 203 | "myMap.addEventListener('mousemove', function(ev) {\n" + | |
| " lat = ev.latlng.lat;\n" + | 204 | 204 | " lat = ev.latlng.lat;\n" + | |
| " lng = ev.latlng.lng;\n" + | 205 | 205 | " lng = ev.latlng.lng;\n" + | |
| "});" | 206 | 206 | "});" | |
| ) | 207 | 207 | ) | |
| } | 208 | 208 | } | |
| 209 | 209 | |||
| fun getMousePosition(): LatLong { | 210 | 210 | fun getMousePosition(): LatLong { | |
| val lat = execScript("lat;") as Double | 211 | 211 | val lat = execScript("lat;") as Double | |
| val lng = execScript("lng;") as Double | 212 | 212 | val lng = execScript("lng;") as Double | |
| return LatLong(lat, lng) | 213 | 213 | return LatLong(lat, lng) | |
| } | 214 | 214 | } | |
| 215 | 215 | |||
| /** | 216 | 216 | /** | |
| * Adds a custom marker type | 217 | 217 | * Adds a custom marker type | |
| * | 218 | 218 | * | |
| * @param markerName the name of the marker type | 219 | 219 | * @param markerName the name of the marker type | |
| * @param iconUrl the url if the marker icon | 220 | 220 | * @param iconUrl the url if the marker icon | |
| */ | 221 | 221 | */ | |
| fun addCustomMarker(markerName: String, iconUrl: String): String { | 222 | 222 | fun addCustomMarker(markerName: String, iconUrl: String): String { | |
| execScript( | 223 | 223 | execScript( | |
| "var $markerName = L.icon({\n" + | 224 | 224 | "var $markerName = L.icon({\n" + | |
| "iconUrl: '${createImage(iconUrl, "png")}',\n" + | 225 | 225 | "iconUrl: '${createImage(iconUrl, "png")}',\n" + | |
| "iconSize: [24, 24],\n" + | 226 | 226 | "iconSize: [24, 24],\n" + | |
| "iconAnchor: [12, 12],\n" + | 227 | 227 | "iconAnchor: [12, 12],\n" + | |
| "});" | 228 | 228 | "});" | |
| ) | 229 | 229 | ) | |
| return markerName | 230 | 230 | return markerName | |
| } | 231 | 231 | } | |
| 232 | 232 | |||
| private fun createImage(path: String, type: String): String { | 233 | 233 | private fun createImage(path: String, type: String): String { | |
| val image = ImageIO.read(File(path)) | 234 | 234 | val image = ImageIO.read(File(path)) | |
| var imageString: String? = null | 235 | 235 | var imageString: String? = null | |
| val bos = ByteArrayOutputStream() | 236 | 236 | val bos = ByteArrayOutputStream() | |
| 237 | 237 | |||
| try { | 238 | 238 | try { | |
| ImageIO.write(image, type, bos) | 239 | 239 | ImageIO.write(image, type, bos) | |
| val imageBytes = bos.toByteArray() | 240 | 240 | val imageBytes = bos.toByteArray() | |
| 241 | 241 | |||
| val encoder = Base64.getEncoder() | 242 | 242 | val encoder = Base64.getEncoder() | |
| imageString = encoder.encodeToString(imageBytes) | 243 | 243 | imageString = encoder.encodeToString(imageBytes) | |
| 244 | 244 | |||
| bos.close() | 245 | 245 | bos.close() | |
| } catch (e: IOException) { | 246 | 246 | } catch (e: IOException) { | |
| e.printStackTrace() | 247 | 247 | e.printStackTrace() | |
| } | 248 | 248 | } | |
| return "data:image/$type;base64,$imageString" | 249 | 249 | return "data:image/$type;base64,$imageString" | |
| } | 250 | 250 | } | |
| 251 | 251 | |||
| /** | 252 | 252 | /** | |
| * Sets the onMarkerClickListener | 253 | 253 | * Sets the onMarkerClickListener | |
| * | 254 | 254 | * | |
| * @param listener the onMarerClickEventListener | 255 | 255 | * @param listener the onMarerClickEventListener | |
| */ | 256 | 256 | */ | |
| fun onMarkerClick(listener: MarkerClickEventListener) { | 257 | 257 | fun onMarkerClick(listener: MarkerClickEventListener) { | |
| val win = execScript("document") as JSObject | 258 | 258 | val win = execScript("document") as JSObject | |
| win.setMember("java", this) | 259 | 259 | win.setMember("java", this) | |
| markerClickEvent.addListener(listener) | 260 | 260 | markerClickEvent.addListener(listener) | |
| } | 261 | 261 | } | |
| 262 | 262 | |||
| /** | 263 | 263 | /** | |
| * Handles the callback from the markerClickEvent | 264 | 264 | * Handles the callback from the markerClickEvent | |
| */ | 265 | 265 | */ | |
| fun markerClick(title: String) { | 266 | 266 | fun markerClick(title: String) { | |
| markerClickEvent.MarkerClickEvent(title) | 267 | 267 | markerClickEvent.MarkerClickEvent(title) | |
| } | 268 | 268 | } | |
| 269 | 269 | |||
| /** | 270 | 270 | /** | |
| * Sets the onMapMoveListener | 271 | 271 | * Sets the onMapMoveListener | |
| * | 272 | 272 | * | |
| * @param listener the MapMoveEventListener | 273 | 273 | * @param listener the MapMoveEventListener | |
| */ | 274 | 274 | */ | |
| fun onMapMove(listener: MapMoveEventListener) { | 275 | 275 | fun onMapMove(listener: MapMoveEventListener) { | |
| val win = execScript("document") as JSObject | 276 | 276 | val win = execScript("document") as JSObject | |
| win.setMember("java", this) | 277 | 277 | win.setMember("java", this) | |
| execScript("myMap.on('moveend', function(e){ document.java.mapMove(myMap.getCenter().lat, myMap.getCenter().lng);});") | 278 | 278 | execScript("myMap.on('moveend', function(e){ document.java.mapMove(myMap.getCenter().lat, myMap.getCenter().lng);});") | |
| mapMoveEvent.addListener(listener) | 279 | 279 | mapMoveEvent.addListener(listener) | |
| } | 280 | 280 | } | |
| 281 | 281 | |||
| /** | 282 | 282 | /** | |
| * Handles the callback from the mapMoveEvent | 283 | 283 | * Handles the callback from the mapMoveEvent | |
| */ | 284 | 284 | */ | |
| fun mapMove(lat: Double, lng: Double) { | 285 | 285 | fun mapMove(lat: Double, lng: Double) { | |
| val latlng = LatLong(lat, lng) | 286 | 286 | val latlng = LatLong(lat, lng) | |
| mapMoveEvent.MapMoveEvent(latlng) | 287 | 287 | mapMoveEvent.MapMoveEvent(latlng) | |
| } | 288 | 288 | } | |
| 289 | 289 | |||
| /** | 290 | 290 | /** | |
| * Sets the onMapClickListener | 291 | 291 | * Sets the onMapClickListener | |
| * | 292 | 292 | * | |
| * @param listener the onMapClickEventListener | 293 | 293 | * @param listener the onMapClickEventListener | |
| */ | 294 | 294 | */ | |
| fun onMapClick(listener: MapClickEventListener) { | 295 | 295 | fun onMapClick(listener: MapClickEventListener) { | |
| val win = execScript("document") as JSObject | 296 | 296 | val win = execScript("document") as JSObject | |
| win.setMember("java", this) | 297 | 297 | win.setMember("java", this) | |
| execScript("myMap.on('click', function(e){ document.java.mapClick(e.latlng.lat, e.latlng.lng);});") | 298 | 298 | execScript("myMap.on('click', function(e){ document.java.mapClick(e.latlng.lat, e.latlng.lng);});") | |
| mapClickEvent.addListener(listener) | 299 | 299 | mapClickEvent.addListener(listener) | |
| } | 300 | 300 | } | |
| 301 | 301 | |||
| /** | 302 | 302 | /** | |
| * Handles the callback from the mapClickEvent | 303 | 303 | * Handles the callback from the mapClickEvent | |
| */ | 304 | 304 | */ | |
| fun mapClick(lat: Double, lng: Double) { | 305 | 305 | fun mapClick(lat: Double, lng: Double) { | |
| val latlng = LatLong(lat, lng) | 306 | 306 | val latlng = LatLong(lat, lng) | |
| mapClickEvent.MapClickEvent(latlng) | 307 | 307 | mapClickEvent.MapClickEvent(latlng) | |
| } | 308 | 308 | } | |
| 309 | 309 | |||
| /** | 310 | 310 | /** | |
| * Draws a track path along the specified positions. | 311 | 311 | * Draws a track path along the specified positions. | |
| * | 312 | 312 | * | |
| * @param positions list of track positions | 313 | 313 | * @param positions list of track positions | |
| */ | 314 | 314 | */ | |
| fun addTrack(positions: List<LatLong>) { | 315 | 315 | fun addTrack(positions: List<LatLong>) { | |
| 316 | 316 | |||
| val jsPositions = positions | 317 | 317 | val jsPositions = positions | |
| .map { " [${it.latitude}, ${it.longitude}]" } | 318 | 318 | .map { " [${it.latitude}, ${it.longitude}]" } | |
| .joinToString(", \n") | 319 | 319 | .joinToString(", \n") | |
| 320 | 320 | |||
| execScript( | 321 | 321 | execScript( | |
| """ | 322 | 322 | """ | |
| |var latLngs = [ | 323 | 323 | |var latLngs = [ | |
| |$jsPositions | 324 | 324 | |$jsPositions | |
| |]; | 325 | 325 | |]; | |
| |var polyline = L.polyline(latLngs, {color: 'red', weight: 2}).addTo(myMap);""".trimMargin() | 326 | 326 | |var polyline = L.polyline(latLngs, {color: 'red', weight: 2}).addTo(myMap);""".trimMargin() | |
| ) | 327 | 327 | ) | |
| } | 328 | 328 | } | |
| 329 | 329 | |||
| fun clearAllLayer() { | 330 | 330 | fun clearAllLayer() { | |
| execScript(""" | 331 | 331 | execScript(""" | |
| myMap.eachLayer(function (layer) { | 332 | 332 | myMap.eachLayer(function (layer) { | |
| map.removeLayer(layer); | 333 | 333 | map.removeLayer(layer); | |
| }); | 334 | 334 | }); | |
| """.trimIndent()) | 335 | 335 | """.trimIndent()) | |
| } | 336 | 336 | } | |
| 337 | 337 | |||
| fun addTrack(positions: List<LatLong>, id: String, color: Color, tooltip: String) { | 338 | 338 | fun addTrack(positions: List<LatLong>, id: String, color: Color, tooltip: String) { | |
| 339 | 339 | |||
| val jsPositions = positions | 340 | 340 | val jsPositions = positions | |
| .map { " [${it.latitude}, ${it.longitude}]" } | 341 | 341 | .map { " [${it.latitude}, ${it.longitude}]" } | |
| .joinToString(", \n") | 342 | 342 | .joinToString(", \n") | |
| 343 | 343 | |||
| val cleanTooltip = tooltip.replace("'", "'") | 344 | 344 | val cleanTooltip = tooltip.replace("'", "'") | |
| execScript( | 345 | 345 | execScript( | |
| """ | 346 | 346 | """ | |
| |var latLngs = [ | 347 | 347 | |var latLngs = [ | |
| |$jsPositions | 348 | 348 | |$jsPositions | |
| |]; | 349 | 349 | |]; | |
| |var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255) | 350 | 350 | |var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255) | |
| .toInt()},${Math.floor(color.getBlue() * 255).toInt()})"; | 351 | 351 | .toInt()},${Math.floor(color.getBlue() * 255).toInt()})"; | |
| |var polyline$id = L.polyline(latLngs, {color: color, weight: 2, zIndexOffset: 200}).bindTooltip('$cleanTooltip', {sticky: true}).addTo(trackGroup)""".trimMargin() | 352 | 352 | |var polyline$id = L.polyline(latLngs, {color: color, weight: 2, zIndexOffset: 200}).bindTooltip('$cleanTooltip', {sticky: true}).addTo(trackGroup)""".trimMargin() | |
| ) | 353 | 353 | ) | |
| } | 354 | 354 | } | |
| 355 | 355 | |||
| fun makeVesselTrackTransparent(id: String) { | 356 | 356 | fun makeVesselTrackTransparent(id: String) { | |
| execScript("polyline$id.setStyle({opacity: 0.5});") | 357 | 357 | execScript("polyline$id.setStyle({opacity: 0.5});") | |
| } | 358 | 358 | } | |
| 359 | 359 | |||
| fun highlightTrack(id: String) { | 360 | 360 | fun highlightTrack(id: String) { | |
| execScript("polyline$id.setStyle({weight: 4});") | 361 | 361 | execScript("polyline$id.setStyle({weight: 4});") | |
| } | 362 | 362 | } | |
| 363 | 363 | |||
| fun normalizeVesselTrack(id: String) { | 364 | 364 | fun normalizeVesselTrack(id: String) { | |
| execScript("polyline$id.setStyle({opacity: 1,weight: 2});") | 365 | 365 | execScript("polyline$id.setStyle({opacity: 1,weight: 2});") | |
| } | 366 | 366 | } |