diff --git a/04_KTO_Interactive_Map/index.html b/04_KTO_Interactive_Map/index.html new file mode 100644 index 0000000..f2035ac --- /dev/null +++ b/04_KTO_Interactive_Map/index.html @@ -0,0 +1,1880 @@ + + + +KTO Interactive Map + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +CHANGJIN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Mission Briefing
+ + + + + +
CallsignBeast5
Times08:40:0008:50:0008:54:0009:00:00
Fuel80005300/4300Laser Code1511
IntelSA-10

+
Package
+ + +
CallsignUHFVHFIDMTCN

+
Airbases
+ + +
TypeLocationAirportTCNGNDTWRAPPATIS

+
Flight Plan
+ + +
STPTLocationActionTOSHdg.Dist.TASMachAlt.Fuel

+
Objectives
+ + +
STPTLocationTarget

+
Support
+ + +
STPTLocationCallsignTypeUHFVHF

+
+ +
+
Weather Briefing
+ + +
CallsignTime010000Z

+
Performance Data
+ + +
TypeAirportRWYELEV.OATQNHPADA

+
Route METARs
+ + +
#StationMETAR

+
Winds and Temperatures Aloft
+ + +
#Station3000 ft6000 ft9000 ft12000 ft18000 ft24000 ft30000 ft

+
+ +
+

Altitude and Velocity

+
+
+ + + + +
+ +
+ +
+ +
+ + + + + + + + +
 
+ + + + + + + + + + + + +
move
zoom-out
zoom-in
bullseye
compass
ruler
symbol
pencil
text
eraser
reset
+
+
+
+
+ + + + +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea +South Korea + +South Korea +South Korea +South Korea +South Korea + +South Korea Airstrips +South Korea Airstrips +South Korea Airstrips +South Korea Airstrips + + +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea + +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea +North Korea + + + + + +North Korea Airstrips + + + + + + + + +North Korea Airstrips +North Korea Airstrips + + +Japan +Japan +Japan +Japan +Japan + + + +China + + + + + +VORTAC +VORTAC +VORTAC + + + +VORTAC + +VORTAC +VORTAC +VORTAC + + + +Legend + +Bullseye + + + + + diff --git a/04_KTO_Interactive_Map/resources/map_airbases.png b/04_KTO_Interactive_Map/resources/map_airbases.png new file mode 100644 index 0000000..a598cf8 Binary files /dev/null and b/04_KTO_Interactive_Map/resources/map_airbases.png differ diff --git a/common/scripts/map_actions.js b/common/scripts/map_actions.js index aa4520a..d8e2313 100644 --- a/common/scripts/map_actions.js +++ b/common/scripts/map_actions.js @@ -97,6 +97,12 @@ var properties = { } }; +const limits = { + zoom_max: 2.5, + zoom_min: 0.5, + wheel_rate_hz: 20 +} + // Toolbar Icons for actions const toolbar = { icon: { @@ -215,7 +221,7 @@ function locateAirport(list) { refreshCanvas(); x = parseInt(coords[0]); y = parseInt(coords[1]); - drawHighlight(context,x,y,radius); + drawHighlight(context,x,y,radius * properties.zoom); // Make the airport the focus window.scrollTo(x-window.innerWidth/2,y-window.innerHeight/2); @@ -532,14 +538,21 @@ function selectVisibility(list) { refreshCanvas(); } +var hotspots; +function storeMapCoordinates() { + var imgMap = document.getElementById("imgMap"); + hotspots = []; + for (area of imgMap.children) hotspots.push(area); +} // Scale the image map coordinates to match the airport overlay image function scaleMap(scale) { var imageMap = document.getElementById("imgMap"); var areas = imageMap.children; + i = 0; for (area of areas) { - area.coordArr = area.coords.split(','); - area.coords = area.coordArr.map(coord => Math.round(coord * scale)).join(','); + var coordArr = hotspots[i++].coords.split(','); + area.coords = coordArr.map(coord => Math.round(coord * scale)).join(','); if (area.alt == "Legend") properties.legend = area.coords; if (area.alt == "Bullseye") bullseye.coords = area.coords; } @@ -827,13 +840,13 @@ function button(e) { break; case "zoom1": - if (id == "zoom1" && properties.zoom > 0.55) { - if (e.shiftKey) properties.zoom = 0.55; + if (id == "zoom1" && properties.zoom > limits.zoom_min) { + if (e.shiftKey) properties.zoom = limits.zoom_min; else properties.zoom -= 0.05; } case "zoom2": - if (id == "zoom2" && properties.zoom < 1.0) { - if (e.shiftKey) properties.zoom = 1; + if (id == "zoom2" && properties.zoom < limits.zoom_max) { + if (e.shiftKey) properties.zoom = limits.zoom_max; else properties.zoom += 0.05; } scaleView(properties.zoom); @@ -1222,6 +1235,33 @@ var pointer_end = function(e) { properties.ctrl = false; } +var wheel_enabled = true; +function enable_wheel() { + wheel_enabled = true; +} + +// Allow zooming with the mouse but limit it to a set wheel rate +// See Limiters (20 hz) and set discrete steps +var mouse_zoom = function(e) { + e.preventDefault(); + + // Normalize deltaY to a consistent step (e.g., 0.1 zoom per scroll) + var zoomStep = Math.sign(e.deltaY) * 0.1; // Adjust step size as needed + var newZoom = properties.zoom - zoomStep; + + // Ensure zoom stays within limits and apply rounding to avoid floating-point drift + if (wheel_enabled && newZoom >= limits.zoom_min && newZoom <= limits.zoom_max) { + properties.zoom = Math.round(newZoom * 100) / 100; // Round to 2 decimal places + scaleView(properties.zoom); + saveSettings(); + refreshCanvas(); + wheel_enabled = false; + setTimeout(function() { + wheel_enabled = true; + }, (1 / limits.wheel_rate_hz) * 1000); + } +}; + // // Canvas and Layer Routines // @@ -1319,51 +1359,47 @@ function setupLayer(layer, width, height) { } var last_zoom = 1; -function scaleView(zoom) { +function scaleView(zoom, event) { // Add event parameter to capture mouse position var dimension = 3840 * properties.zoom; var dim_str = dimension.toString() + "px"; var scale = properties.zoom / last_zoom; var scroll_element = document.scrollingElement; - var scroll_top = scroll_element.scrollTop; - var scroll_left = scroll_element.scrollLeft; - var scroll_height = scroll_element.scrollHeight; - var scroll_width = scroll_element.scrollWidth; - var client_height = scroll_element.clientHeight; var client_width = scroll_element.clientWidth; - var scroll_left_ratio = scroll_left / scroll_width; - var scroll_top_ratio = scroll_top / scroll_height; - var offset_right = scroll_width - (scroll_left + client_width); - var offset_bottom = scroll_height - (scroll_top + client_height); - - scroll_element.scrollTop = scroll_height * scroll_top_ratio * scale; - scroll_element.scrollLeft = scroll_width * scroll_left_ratio * scale; + var client_height = scroll_element.clientHeight; - var new_offset_right = scroll_element.scrollWidth * scale - (scroll_element.scrollLeft + client_width); - var new_offset_bottom = scroll_element.scrollHeight * scale - (scroll_element.scrollTop + client_height); - var diff_right = offset_right - new_offset_right; - var diff_bottom = offset_bottom - new_offset_bottom; + // Get mouse position relative to the viewport + var mouseX = event ? event.clientX : client_width / 2; // Fallback to center if no event + var mouseY = event ? event.clientY : client_height / 2; - scroll_element.scrollTop = scroll_element.scrollTop - (diff_bottom / 2) / 2; - scroll_element.scrollLeft = scroll_element.scrollLeft - (diff_right / 2) / 2; + // Calculate mouse position relative to the document before scaling + var doc_mouseX = scroll_element.scrollLeft + mouseX; + var doc_mouseY = scroll_element.scrollTop + mouseY; + // Update map dimensions var base_map = document.getElementById('map'); - base_map.style.height = dim_str; base_map.style.width = dim_str; + base_map.style.height = dim_str; var ovly_map = document.getElementById('airbases'); - ovly_map.style.height = dim_str; ovly_map.style.width = dim_str; - ovly_map.useMap = "#Map"; - + ovly_map.style.height = dim_str; window.canvas.width = dimension; window.canvas.height = dimension; + // Scale bullseye coordinates bullseye.x *= scale; bullseye.y *= scale; - // Adjust the airport coordinates on the image map + // Scale the airport coordinates on the image map scaleMap(scale); + + // Calculate new scroll position to keep mouse point fixed + var new_doc_mouseX = doc_mouseX * scale; + var new_doc_mouseY = doc_mouseY * scale; + scroll_element.scrollLeft = new_doc_mouseX - mouseX; + scroll_element.scrollTop = new_doc_mouseY - mouseY; + last_zoom = properties.zoom; } @@ -1615,7 +1651,9 @@ window.onload = function(e) { // Adjust map to used scale // Safari will slow beyond 3840 canvas size + storeMapCoordinates(); scaleMap(3840/4096); + storeMapCoordinates(); // Setup the Layers to be rendered on the main canvas setupLayer(layer.mission, canvas.width, canvas.height ); @@ -1640,6 +1678,7 @@ window.onload = function(e) { this.addEventListener('mousedown', pointer_start); this.addEventListener('mousemove', pointer_drag); this.addEventListener('mouseup', pointer_end); + this.addEventListener("wheel", mouse_zoom, {passive:false} ); // Trigger a Render updateToolbar(); @@ -1648,6 +1687,7 @@ window.onload = function(e) { window.scrollTo(bullseye.x-window.innerWidth/2,bullseye.y-window.innerHeight/2); // Draw the Layers + enable_wheel(); scaleView(properties.zoom); refreshCanvas(); } diff --git a/index.html b/index.html index ce59b3a..728951d 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,14 @@ -Falcon BMS - Interactive Maps (BMS 4.37) +Falcon BMS - Interactive Maps -
-
- -
+
+
+ + +
+
+
-

Falcon BMS 4.37 - Interactive Maps


- You find here Interactive Maps providing access to airbase and airstrip information for the respective theater of operations. The maps provide the following features: -
    -
  • Locate airports and navigation beacons and request their information by hovering over them
  • -
  • Move map, zoom in/out and measure distances on map
  • -
  • Mission.ini or Pilot.ini drag and drop to show route on map and more.
  • -
  • Full whiteboard collaboration using collaboration server
  • -
  • Save Whiteboard(.png) and restore with drag and drop
  • -
  • MIL-STD-2525D symbology
  • -
  • Weather import (fmap drop) for weather charts (Temperature, Doppler, Winds, Isobars)
  • -
  • Route Waypoint dialog (actions, heading, distance and duration updates, etc)
  • -
  • Computed Mission Flight Info, Mission Radio Frequencies and Mission Objectives
  • -
  • Show Lat/Long on map and x,y of image map
  • -
  • Aerodrome Weather Report (METAR) as tooltips and on route dialog (uses) fmap
  • -
  • Add notes on Whiteboard
  • -
  • Bullseye placement
  • -
  • Download and Import GFS data and files
  • -
-
Change log  |  Manual (PDF)
-
+

Falcon BMS - Interactive Maps


+

Theater Maps 4.37

+ @@ -169,7 +119,7 @@
@@ -177,7 +127,7 @@
@@ -185,7 +135,7 @@
@@ -193,7 +143,76 @@
Korea Theater
UNDER CONSTRUCTION +
+ + + + + + + + + + + + +
Korea Theater
Rev: 26 JUNE 2023
Balkans Theater
Rev: 26 JUNE 2023
Israel Theater
Rev: 26 JUNE 2023
Balkans Theater
UNDER CONSTRUCTION
Israel Theater
UNDER CONSTRUCTION
Hellenic Theater
UNDER CONSTRUCTION
+
+
+ Korea Theater +
+ +
+
+
+
+ Balkans Theater +
+ +
+
+
+
+ Israel Theater +
+ +
+
+
+
+ Hellenic Theater +
+ +
+
+
+

Map Features

+ The maps provide the following features: +
    +
  • Locate airports and navigation beacons and request their information by hovering over them
  • +
  • Move map, zoom in/out and measure distances on map
  • +
  • Mission.ini or Pilot.ini drag and drop to show route on map and more.
  • +
  • Full whiteboard collaboration using collaboration server
  • +
  • Save Whiteboard(.png) and restore with drag and drop
  • +
  • MIL-STD-2525D symbology
  • +
  • Weather import (fmap drop) for weather charts (Temperature, Doppler, Winds, Isobars)
  • +
  • Route Waypoint dialog (actions, heading, distance and duration updates, etc)
  • +
  • Computed Mission Flight Info, Mission Radio Frequencies and Mission Objectives
  • +
  • Show Lat/Long on map and x,y of image map
  • +
  • Aerodrome Weather Report (METAR) as tooltips and on route dialog (uses) fmap
  • +
  • Download and Import GFS data and files
  • +
  • Bullseye placement
  • +
+
Change log  |  Manual (PDF)
+
- \ No newline at end of file +