You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
6.3 KiB

  1. var map = L.map('map', { zoomControl: false }).setView([45.516, -122.660], 14, null, null, 24);
  2. // var layer = L.esri.basemapLayer("Topographic");
  3. // layer.maxZoom = 24;
  4. // layer.maxNativeZoom = 24;
  5. // layer.addTo(map);
  6. var opts = {
  7. attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
  8. maxZoom: 24,
  9. zoomOffset: -1,
  10. tileSize: 512,
  11. id: 'mapbox/light-v10',
  12. accessToken: 'pk.eyJ1IjoiYWFyb25wayIsImEiOiJja3A0eXV2ZXIwMGt3MnVuc2Uzcm1yYzFuIn0.-_qwPOLRiQk8t56xs6vkfg'
  13. };
  14. L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', opts).addTo(map);
  15. new L.Control.Zoom({ position: 'topleft' }).addTo(map);
  16. var geojsonLineOptions = {
  17. color: "#0033ff",
  18. weight: 4,
  19. opacity: 0.5
  20. };
  21. var startIcon = L.icon({
  22. iconUrl: '/assets/map-pin-start.png',
  23. iconSize: [18,28],
  24. iconAnchor: [9,28]
  25. });
  26. var endIcon = L.icon({
  27. iconUrl: '/assets/map-pin-end.png',
  28. iconSize: [18,28],
  29. iconAnchor: [9,28]
  30. });
  31. var visible_layers = [];
  32. var visible_data = [];
  33. var highlightedMarker;
  34. var animatedMarker;
  35. var startMarker;
  36. var endMarker;
  37. var timers = [];
  38. function resetAnimation() {
  39. if(animatedMarker) {
  40. map.removeLayer(animatedMarker);
  41. }
  42. if(timers.length > 0) {
  43. for(var i in timers) {
  44. clearTimeout(timers[i]);
  45. }
  46. }
  47. }
  48. function displayLineOnMap(response, options) {
  49. var data = response.linestring;
  50. if(data.coordinates && data.coordinates.length > 0) {
  51. // For any null coordinates, fill it in with the previous location
  52. var lastCoord = null;
  53. for(var i in data.coordinates) {
  54. if(data.coordinates[i] == null) {
  55. data.coordinates[i] = lastCoord;
  56. } else {
  57. lastCoord = data.coordinates[i];
  58. }
  59. }
  60. visible_data.push(data);
  61. visible_layers.push(L.geoJson(data, {
  62. style: geojsonLineOptions
  63. }).addTo(map));
  64. // Show the start/end pins if necessary
  65. if(options.pins) {
  66. startMarker = L.marker(pointFromGeoJSON(visible_data[0].coordinates[0]), {icon: startIcon});
  67. startMarker.addTo(map);
  68. endMarker = L.marker(pointFromGeoJSON(visible_data[0].coordinates[ visible_data[0].coordinates.length-1 ]), {icon: endIcon});
  69. endMarker.addTo(map);
  70. }
  71. // If the new layer is completely outside the current view, zoom the map to fit all layers
  72. var vlayer = visible_layers[visible_layers.length - 1];
  73. var is_outside = false;
  74. if(!map.getBounds().intersects(vlayer.getBounds())) {
  75. is_outside = true;
  76. }
  77. if(is_outside) {
  78. console.log('is outside');
  79. console.log(vlayer);
  80. var full_bounds;
  81. for(var i in visible_layers) {
  82. if(visible_layers[i].getBounds) {
  83. if(full_bounds) {
  84. full_bounds.extend(visible_layers[i].getBounds());
  85. } else {
  86. full_bounds = visible_layers[i].getBounds();
  87. }
  88. }
  89. }
  90. map.fitBounds(full_bounds);
  91. }
  92. showBatteryGraph(response);
  93. }
  94. }
  95. jQuery(function($){
  96. $('.calendar a').click(function(evt){
  97. var append = evt.altKey;
  98. if(!append) {
  99. removeVisibleLayers();
  100. }
  101. $(this).addClass('selected');
  102. resetAnimation();
  103. var db_name = $("#database").data("name");
  104. var db_token = $("#database").data("token");
  105. $.get("/api/query?format=linestring&date="+$(this).data('date')+"&tz="+$("#timezone").val()+"&token="+db_token, function(data){
  106. displayLineOnMap(data, {pins: false});
  107. });
  108. $("#range-from").val($(this).data('date')+' 00:00:00');
  109. $("#range-to").val($(this).data('date')+' 23:59:59');
  110. return false;
  111. });
  112. $('#range-go').click(function(evt) {
  113. var stateObj = {from: $('#range-from').val(), to: $('#range-to').val(), tz: $('#timezone').val()};
  114. var baseURL = "/map/" + $("#database").data('name');
  115. var historyURL = baseURL + "?from="+stateObj.from+"&to="+stateObj.to+"&tz="+stateObj.tz;
  116. window.history.pushState(stateObj, "GPS Log", historyURL)
  117. resetAnimation();
  118. removeVisibleLayers();
  119. $("#range-go").addClass("loading");
  120. var db_token = $("#database").data("token");
  121. $.get("/api/query?format=linestring&start="+$('#range-from').val()+"&end="+$('#range-to').val()+"&tz="+$("#timezone").val()+"&token="+db_token, function(data){
  122. $("#range-go").removeClass("loading");
  123. $("#trip-create-form").removeClass("hidden");
  124. displayLineOnMap(data, {pins: true});
  125. });
  126. return false;
  127. })
  128. $('#btn-play').click(function(){
  129. console.log(visible_data[0].coordinates[0]);
  130. var point = pointFromGeoJSON(visible_data[0].coordinates[0]);
  131. resetAnimation();
  132. animatedMarker = L.marker(point);
  133. animatedMarker.addTo(map);
  134. timers = [];
  135. var interval = 3;
  136. for(var i in visible_data[0].coordinates) {
  137. (function(i){
  138. timers.push(setTimeout(function(){
  139. point = pointFromGeoJSON(visible_data[0].coordinates[i]);
  140. animatedMarker.setLatLng(point);
  141. }, interval*i));
  142. })(i);
  143. }
  144. });
  145. $("#trip-create").click(function(){
  146. $("#trip-create").addClass("loading");
  147. $.post('/api/trip-complete', {
  148. start: $("#range-from").val(),
  149. end: $("#range-to").val(),
  150. tz: $("#timezone").val(),
  151. mode: $("#trip-mode").val(),
  152. token: $("#database").data("write-token")
  153. }, function(response) {
  154. $("#trip-create").removeClass("loading");
  155. });
  156. });
  157. if($("#range-from").val() == "") {
  158. console.log("Autoselecting calendar day");
  159. $(".calendar a[data-date="+((new Date()).toISOString().slice(0,10))+"]").focus().click();
  160. } else {
  161. console.log("Loading range");
  162. $("#range-go").click();
  163. }
  164. });
  165. function removeVisibleLayers() {
  166. $('.calendar a').removeClass('selected');
  167. if(visible_layers.length) {
  168. for(var i in visible_layers) {
  169. map.removeLayer(visible_layers[i]);
  170. }
  171. }
  172. visible_layers = [];
  173. visible_data = [];
  174. if(startMarker) {
  175. map.removeLayer(startMarker);
  176. map.removeLayer(endMarker);
  177. }
  178. }
  179. function moveMarkerToPosition(point) {
  180. if(point.location) {
  181. var coord = pointFromGeoJSON(point.location);
  182. if(coord) {
  183. if(!highlightedMarker) {
  184. highlightedMarker = L.marker(coord).addTo(map);
  185. } else {
  186. highlightedMarker.setLatLng(coord);
  187. }
  188. }
  189. }
  190. }
  191. function pointFromGeoJSON(geo) {
  192. return L.latLng(geo[1], geo[0])
  193. }