// // Copyright (c) 2021 Clementine Computing LLC. // // This file is part of RideLogic. // // RideLogic is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // RideLogic is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with RideLogic. If not, see . // var g_info = { "geojson" : {}, "route" : {}, "route_path": {}, "active_route" : [], "ol_route_layer" : {} }; var Feature = ol.Feature; var Map = ol.Map; var Overlay = ol.Overlay; var Point = ol.geom.Point; var TileJSON = ol.source.TileJSON; var VectorSource = ol.source.Vector; var View = ol.View; var Icon = ol.style.Icon; var Style = ol.style.Style; var TileLayer = ol.layer.Tile; var VectorLayer = ol.layer.Vector; var OSM = ol.source.OSM; var fromLonLat = ol.proj.fromLonLat; var Control = ol.control.Control; var LineString = ol.geom.LineString; //var defaultLonLat = [ -76.5019, 42.4440]; //var defaultLonLat = [ -76.1805, 42.6012 ]; var defaultLonLat = [ -76.2705, 42.5512 ]; var defaultWebMerc = fromLonLat(defaultLonLat); function _rnd(a,b) { a = ((typeof a == "undefined") ? 1.0 : a); if (typeof b === "undefined") { return Math.random()*a; } return Math.random()*(b-a) + a; } function example_change_pos() { let w = 1/16.0; let lonlat = [ defaultLonLat[0] + _rnd(-w,w), defaultLonLat[1] + _rnd(-w,w)]; let merc = fromLonLat(lonlat); _icon[0].feature.getGeometry().setCoordinates(merc); busLayer.getSource().changed(); } function example_change_opacity(p) { p = ((typeof p === "undefined") ? 0.0 : p); _icon[0].style.getImage().setOpacity(p); busLayer.getSource().changed(); } // icon can't change image src dynamically, // so have to replace. // See https://stackoverflow.com/questions/57341190/how-can-i-change-icon-source-dynamically // function example_change_image() { let _nuimg = new Icon({ anchor: [0.5, 46], anchorXUnits: 'fraction', anchorYUnits: 'pixels', src: 'data/bus_gw_90.png', }); _icon[0].style.setImage(_nuimg); busLayer.getSource().changed(); } //--- var vectorSource = new VectorSource(); var _icon = []; for (let ii=0; ii<2; ii++) { let w = 1/32.0; let lonlat = [ defaultLonLat[0] + _rnd(-w,w), defaultLonLat[1] + _rnd(-w,w)]; let merc = fromLonLat(lonlat); let iconFeature = new Feature({ geometry: new Point([merc[0], merc[1]]), name: 'bus' }); let iconStyle = new Style({ image: new Icon({ anchor: [0.5, 46], anchorXUnits: 'fraction', anchorYUnits: 'pixels', src: 'data/icon.png', }), }); iconStyle.getImage().setOpacity(0.0); _icon.push({ "style": iconStyle, "feature": iconFeature }); iconFeature.setStyle(iconStyle); vectorSource.addFeature(iconFeature); } //--- const busLayer = new VectorLayer({ source: vectorSource, zIndex: 2 }); //-- const rasterLayer = new TileLayer({ //source: ol.source.OSM() source: new ol.source.OSM(), }); //-- //------------------- //------------------- //------------------- const g_map = new Map({ //layers: [rasterLayer, vectorLayer, routeLayer], layers: [rasterLayer, busLayer ], target: document.getElementById('map'), controls:[], view: new View({ center: defaultWebMerc, zoom: 11, }), }); var g_side_toggle = true; function toggle_sidebar(tf) { g_side_toggle = (g_side_toggle ? false : true); if (typeof tf !== "undefined") { g_side_toggle = tf; } // my perpetual fight with CSS. // I can't seem to get these values in when I put them in the // CSS, so we do it here programatically. // // Create a scrollable bar only for the list and not // for the map. // Hide the scroll bar when collapsing. // Hide the x scrollbar but dumping x values that overflow. // let ele = document.getElementById("sidebar-wrapper"); if (g_side_toggle) { ele.style["overflow-y"] = "auto"; ele.style["overflow-x"] = "hidden"; ele.style["margin-left"] = 0; ele.style["min-width"] = "15rem"; ele.style["max-height"] = "100vh"; } else { ele.style["overflow-y"] = "hidden"; ele.style["overflow-x"] = "hidden"; ele.style["margin-left"] = "-15rem"; ele.style["min-width"] = "0"; ele.style["max-height"] = "100vh"; } } class CustomToggle extends Control { constructor(opt) { opt = opt || {}; let ele = document.createElement("button"); ele.id = 'ui_route_toggle'; ele.innerHTML = "Route"; // class="btn" id="sidebarToggle" style='display:float;' ele.classList.add("custom-button"); super({ element: ele, target: opt.target }); ele.addEventListener('click', this.fire.bind(this), false); } fire() { toggle_sidebar(); // hacky, but functional // setTimeout(resize_map, 250); } } // button to toggle side bar route list // g_map.addControl(new CustomToggle({ className: 'custom-button' })); //------------------- //------------------- //------------------- g_map.addControl(new ol.control.Zoom({ className: 'custom-zoom' })); const element = document.getElementById('popup'); const popup = new Overlay({ element: element, positioning: 'bottom-center', stopEvent: false, }); g_map.addOverlay(popup); // display popup on click // g_map.on('click', function (evt) { // not working (wip) // /* const feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) { return feature; }); */ }); // change mouse cursor when over marker g_map.on('pointermove', function (e) { const pixel = g_map.getEventPixel(e.originalEvent); const hit = g_map.hasFeatureAtPixel(pixel); g_map.getTarget().style.cursor = hit ? 'pointer' : ''; }); // Close the popup when the map is moved // g_map.on('movestart', function () { //$(element).popover('dispose'); }); g_map.on("postrender", function(event) { //console.log("bang..."); }); //----- function update_buses(json_gtfs) { let bearingIdxLookup = [ "0", "45", "90", "135", "180", "225", "270", "315" ]; for (let ii=0; ii 7) { iheading = 0; } let _nuimg = new Icon({ anchor: [0.5, 46], anchorXUnits: 'fraction', anchorYUnits: 'pixels', src: 'data/bus_gw_' + bearingIdxLookup[iheading] + '.png', }); _icon[ii].style.setImage(_nuimg); _icon[ii].style.getImage().setOpacity(1.0); //console.log(">>", id, lat, lon, bearing); } busLayer.getSource().changed(); } function fetch_gtfs_vehicle_position() { let xhr = new XMLHttpRequest(); xhr.onload = function() { let ab = xhr.response; let json_pb = pb2json.pb2json(ab); //console.log(">>>", json_pb); update_buses(json_pb) }; xhr.responseType = "arraybuffer"; xhr.open("GET", "VehiclePosition.pb"); xhr.send(); } //-- function ui_show_single_route(route_id) { if (!(route_id in g_info.ol_route_layer)) { console.log("route", route_id, "not found in g_info.ol_route_layer"); return; } for (let i=0; i