Improved www.ttss.krakow.pl
Jacek Kowalski
2017-04-15 adaa1f628f04a6af247e142edbea679578b90fef
commit | author | age
e5c5bd 1 <!DOCTYPE HTML>
JK 2 <html>
3 <head>
8338a5 4 <title>MPK Kraków Map</title>
e5c5bd 5 <style type="text/css">
JK 6 html, body, #map {
7     width: 100%;
8     height: 100%;
9     margin: 0;
10 }
8338a5 11 #popup {
JK 12     color: black;
13     background: white;
14     padding: 5px;
15     border: 1px solid black;
16     border-radius: 10px;
17     font: 12px sans-serif;
18 }
19 #popup p {
20     margin: 0;
21     padding: 5px;
22 }
23 #popup .line-direction {
24     font-weight: bold;
25 }
e5c5bd 26 </style>
8338a5 27 <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha384-3ceskX3iaEnIogmQchP8opvBy3Mi7Ce34nWjpBIwVTHfGYWQS9jwHDVRnpKKHJg7" crossorigin="anonymous"></script>
e5c5bd 28 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList"></script>
8338a5 29 <script src="https://openlayers.org/en/v4.0.1/build/ol.js" integrity="sha384-DjqoiOTAYD0bxdY6K1Ep7Xd4QQc46AKzKmkgC4+rnKX47PniPHIjRt02uhT8C04h" crossorigin="anonymous"></script>
e5c5bd 30 <script tyle="text/javascript" src="lang_en.js" id="lang_script"></script>
8338a5 31 <script tyle="text/javascript" src="common.js"></script>
e5c5bd 32 </head>
JK 33 <body>
34 <div id="map"><div id="popup"></div></div>
35
36 <script tyle="text/javascript">
37 //var ttss_base = 'http://www.ttss.krakow.pl/internetservice';
38 var ttss_base = '/proxy.php';
39 var ttss_refresh = 5000; // 5 seconds
40
41 var vehicles_xhr = null;
42 var vehicles_timer = null;
8338a5 43 var vehicles_last_update = 0;
adaa1f 44 var vehicles_source = null;
JK 45 var vehicles_layer = null;
46
47 var stops_xhr = null;
48 var stops_source = null;
49 var stops_layer = null;
50 var stop_points_source = null;
51 var stop_points_layer = null;
e5c5bd 52
JK 53 var map = null;
8338a5 54 var popup_feature_id = null;
e5c5bd 55 var popup_element = document.getElementById('popup');
JK 56 var popup = null;
57
58 function fail(msg) {
59     console.log(msg);
60     alert(msg);
61 }
62
63 function fail_ajax(data) {
64     // abort() is not a failure
65     if(data.readyState == 0 && data.statusText == 'abort') return;
66     
67     if(data.status == 0) {
68         fail(lang.error_request_failed_connectivity, data);
69     } else if (data.statusText) {
70         fail(lang.error_request_failed_status.replace('$status', data.statusText), data);
71     } else {
72         fail(lang.error_request_failed, data);
73     }
74 }
75
d696cf 76 function popupHide() {
JK 77     popup.setPosition(undefined);
78     popup_feature_id = null;
79 }
80
81 function popupShow(coordinates, id) {
82     popup.setPosition(coordinates);
83     if(id) {
84         popup_feature_id = id;
85     }
86 }
87
adaa1f 88 function getGeometry(object) {
JK 89     return new ol.geom.Point(ol.proj.fromLonLat([object.longitude / 3600000.0, object.latitude / 3600000.0]))
90 }
91
e5c5bd 92 function init() {
JK 93     if(!window.jQuery) {
94         fail(lang.jquery_not_loaded);
95         return;
96     }
97     
98     $.ajaxSetup({
99         dataType: 'json',
100         timeout: 10000,
101     });
102     
103     
adaa1f 104     
JK 105     stops_source = new ol.source.Vector({
106         features: [],
107     });
108     stops_layer = new ol.layer.Vector({
109         source: stops_source,
110     });
111     
112     stop_points_source = new ol.source.Vector({
113         features: [],
114     });
115     stop_points_layer = new ol.layer.Vector({
116         source: stop_points_source,
117         visible: false,
118     });
119     
e5c5bd 120     vehicles_source = new ol.source.Vector({
adaa1f 121         features: [],
JK 122     });
123     vehicles_layer = new ol.layer.Vector({
124         source: vehicles_source,
e5c5bd 125     });
JK 126     
127     popup = new ol.Overlay({
128         element: popup_element,
129         positioning: 'bottom-center',
130         stopEvent: false,
8338a5 131         offset: [0, -12]
e5c5bd 132     });
JK 133     
134     map = new ol.Map({
135         target: 'map',
136         layers: [
137             new ol.layer.Tile({
138                 source: new ol.source.OSM()
139             }),
adaa1f 140             stops_layer,
JK 141             stop_points_layer,
142             vehicles_layer,
e5c5bd 143         ],
JK 144         overlays: [popup],
145         view: new ol.View({
146             center: ol.proj.fromLonLat([19.94, 50.06]),
147             zoom: 13
148         })
149     });
150     
adaa1f 151     // Display popup on click
d696cf 152     map.on('singleclick', function(e) {
JK 153         var feature = map.forEachFeatureAtPixel(e.pixel, function(feature) { return feature; });
8338a5 154         if(feature) {
e5c5bd 155             var coordinates = feature.getGeometry().getCoordinates();
8338a5 156             
JK 157             deleteChildren(popup_element);
adaa1f 158             switch(feature.getId().substr(0, 1)) {
JK 159                 case 'v':
160                     addParaWithText(popup_element, feature.get('name')).className = 'line-direction';
161                     
162                     var vehicle_type = parseVehicle(feature.get('id'));
163                     if(vehicle_type) {
164                         addParaWithText(popup_element, vehicle_type.num + ' ' + vehicle_type.type);
165                     }
166                     break;
167                 case 's':
168                 case 'p':
169                     addParaWithText(popup_element, feature.get('name')).className = 'line-direction';
170                     break;
171                 
8338a5 172             }
JK 173             
d696cf 174             popupShow(coordinates, feature.getId());
e5c5bd 175         } else {
d696cf 176             popupHide();
e5c5bd 177         }
JK 178     });
179
adaa1f 180     // Change mouse cursor when over marker
e5c5bd 181     map.on('pointermove', function(e) {
8c66c4 182         var hit = map.hasFeatureAtPixel(e.pixel);
JK 183         var target = map.getTargetElement();
184         target.style.cursor = hit ? 'pointer' : '';
adaa1f 185     });
JK 186     
187     // Change layer visibility on zoom
188     map.getView().on('change:resolution', function(e) {
189         if(map.getView().getZoom() >= 16) {
190             stops_layer.setVisible(false);
191             stop_points_layer.setVisible(true);
192         } else {
193             stops_layer.setVisible(true);
194             stop_points_layer.setVisible(false);
195         }
e5c5bd 196     });
JK 197 }
198
199 function updateVehicles() {
200     if(vehicles_timer)clearTimeout(vehicles_timer);
201     if(vehicles_xhr) vehicles_xhr.abort();
202     
203     vehicles_xhr = $.get(
204         ttss_base + '/geoserviceDispatcher/services/vehicleinfo/vehicles' 
205             + '?positionType=CORRECTED'
206             + '&colorType=ROUTE_BASED'
8338a5 207             + '&lastUpdate=' + encodeURIComponent(vehicles_last_update)
e5c5bd 208     ).done(function(data) {
8338a5 209         vehicles_last_update = data.lastUpdate;
JK 210         
e5c5bd 211         for(var i = 0; i < data.vehicles.length; i++) {
JK 212             var vehicle = data.vehicles[i];
213             
adaa1f 214             var vehicle_feature = vehicles_source.getFeatureById('v' + vehicle.id);
e5c5bd 215             if(vehicle.isDeleted) {
JK 216                 if(vehicle_feature) {
217                     vehicles_source.removeFeature(vehicle_feature);
adaa1f 218                     if(popup_feature_id == vehicle_feature.getId()) {
b1154d 219                         popupHide();
JK 220                     }
e5c5bd 221                 }
JK 222                 continue;
223             }
224             
225             var vehicle_name_space = vehicle.name.indexOf(' ');
226             vehicle.line = vehicle.name.substr(0, vehicle_name_space);
227             vehicle.direction = vehicle.name.substr(vehicle_name_space+1);
8338a5 228             if(special_directions[vehicle.direction]) {
JK 229                 vehicle.line = special_directions[vehicle.direction];
230             }
231             
adaa1f 232             vehicle.geometry = getGeometry(vehicle);
8338a5 233             vehicle.vehicle_type = parseVehicle(vehicle.id);
e5c5bd 234             
JK 235             if(!vehicle_feature) {
236                 vehicle_feature = new ol.Feature(vehicle);
adaa1f 237                 vehicle_feature.setId('v' + vehicle.id);
8338a5 238                 
JK 239                 var color_type = 'black';
240                 if(vehicle.vehicle_type) {
241                     switch(vehicle.vehicle_type.low) {
242                         case 0:
243                             color_type = 'orange';
244                             break;
245                         case 1:
246                             color_type = 'blue';
247                             break;
248                         case 2:
249                             color_type = 'green';
250                             break;
251                     }
252                 }
253                 
e5c5bd 254                 vehicle_feature.setStyle(new ol.style.Style({
JK 255                     image: new ol.style.RegularShape({
256                         fill: new ol.style.Fill({color: '#3399ff'}),
8338a5 257                         stroke: new ol.style.Stroke({color: color_type, width: 2}),
e5c5bd 258                         points: 3,
JK 259                         radius: 12,
d4eb9e 260                         rotation: Math.PI * parseFloat(vehicle.heading) / 180.0,
JK 261                         rotateWithView: true,
e5c5bd 262                         angle: 0
JK 263                     }),
264                     text: new ol.style.Text({
8338a5 265                         font: 'bold 10px sans-serif',
e5c5bd 266                         text: vehicle.line,
JK 267                         fill: new ol.style.Fill({color: 'white'}),
268                     }),
269                 }));
270                 vehicles_source.addFeature(vehicle_feature);
271             } else {
272                 vehicle_feature.setProperties(vehicle);
d4eb9e 273                 vehicle_feature.getStyle().getImage().setRotation(Math.PI * parseFloat(vehicle.heading) / 180.0);
d696cf 274                 
JK 275                 if(popup_feature_id == vehicle_feature.getId()) {
276                     popupShow(vehicle_feature.getGeometry().getCoordinates());
8338a5 277                 }
e5c5bd 278             }
JK 279         }
280         
281         vehicles_timer = setTimeout(function(){ 
282             updateVehicles();
283         }, ttss_refresh);
284     }).fail(fail_ajax);
285 }
286
adaa1f 287 function updateStopSource(stops, prefix, source) {
JK 288     source.clear();
289     
290     for(var i = 0; i < stops.length; i++) {
291         var stop = stops[i];
292         stop.geometry = getGeometry(stop);
293         var stop_feature = new ol.Feature(stop);
294         
295         stop_feature.setId(prefix + stop.id);
296         stop_feature.setStyle(new ol.style.Style({
297             image: new ol.style.Circle({
298                 fill: new ol.style.Fill({color: 'orange'}),
299                 stroke: new ol.style.Stroke({color: 'red', width: 1}),
300                 radius: 3,
301             }),
302         }));
303         
304         source.addFeature(stop_feature);
305     }
306 }
307
308 function updateStops() {
309     $.get(
310         ttss_base + '/geoserviceDispatcher/services/stopinfo/stops'
311             + '?left=-648000000'
312             + '&bottom=-324000000'
313             + '&right=648000000'
314             + '&top=324000000'
315     ).done(function(data) {
316         updateStopSource(data.stops, 's', stops_source);
317     }).fail(fail_ajax);
318 }
319 function updateStopPoints() {
320     $.get(
321         ttss_base + '/geoserviceDispatcher/services/stopinfo/stopPoints'
322             + '?left=-648000000'
323             + '&bottom=-324000000'
324             + '&right=648000000'
325             + '&top=324000000'
326     ).done(function(data) {
327         updateStopSource(data.stopPoints, 'p', stop_points_source);
328     }).fail(fail_ajax);
329 }
330
e5c5bd 331 init();
JK 332 updateVehicles();
adaa1f 333 updateStops();
JK 334 updateStopPoints();
e5c5bd 335 </script>
JK 336 </body>
337 </html>