OpenLayers API
This commit is contained in:
parent
160773929a
commit
8c9a527fdf
13
README
13
README
@ -1,15 +1,15 @@
|
|||||||
This is a simple web viewer for GPS tracks uploaded with mobile client.
|
This is a simple web viewer for GPS tracks uploaded with mobile client.
|
||||||
It is designed to work with Android version of great app TrackMe (http://www.luisespinosa.com/trackme_eng.html),
|
It is designed to work with Android version of great app TrackMe (http://www.luisespinosa.com/trackme_eng.html),
|
||||||
but it should be easy to adjust it for other clients.
|
but it should be easy to adjust it for other clients (other database tables).
|
||||||
Interface "look and feel" is based on TrackMe Display (http://forum.xda-developers.com/showthread.php?t=477394).
|
Interface "look and feel" is based on TrackMe Display (http://forum.xda-developers.com/showthread.php?t=477394).
|
||||||
It currently uses Google Maps API, but work on OpenStreetMap is in progress.
|
It is possible to switch between Google Maps API and OpenLayers API with OpenStreetMap (any other base layer should be easy to add).
|
||||||
|
|
||||||
Live demo:
|
Live demo:
|
||||||
- http://flaa.fabiszewski.net/phptrackme/
|
- http://flaa.fabiszewski.net/phptrackme/
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
- php 5
|
- PHP 5.1.2
|
||||||
- mysql
|
- MYSQL 4.1
|
||||||
- browser with javascript enabled, cookies for authentication
|
- browser with javascript enabled, cookies for authentication
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
@ -20,12 +20,13 @@ Features:
|
|||||||
- multiple users
|
- multiple users
|
||||||
- user authentication
|
- user authentication
|
||||||
- Google Maps API v3
|
- Google Maps API v3
|
||||||
|
- OpenLayers 2.13
|
||||||
- ajax
|
- ajax
|
||||||
- server based configuration
|
- server based configuration
|
||||||
|
|
||||||
Todo
|
Todo
|
||||||
- OpenStreetMap API
|
- install script
|
||||||
- client based configuration
|
- user level customization, storing settings in cookies?
|
||||||
- write opensource client?
|
- write opensource client?
|
||||||
|
|
||||||
License
|
License
|
||||||
|
173
api_gmaps.js
Executable file
173
api_gmaps.js
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
/* phpTrackme
|
||||||
|
*
|
||||||
|
* Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net)
|
||||||
|
*
|
||||||
|
* This is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Library General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// google maps
|
||||||
|
var map;
|
||||||
|
var polies = new Array();
|
||||||
|
var markers = new Array();
|
||||||
|
var popups = new Array();
|
||||||
|
var polyOptions;
|
||||||
|
var mapOptions;
|
||||||
|
var loadedAPI = 'gmaps';
|
||||||
|
function init() {
|
||||||
|
google.maps.visualRefresh = true;
|
||||||
|
polyOptions = {
|
||||||
|
strokeColor: '#FF0000',
|
||||||
|
strokeOpacity: 1.0,
|
||||||
|
strokeWeight: 2
|
||||||
|
}
|
||||||
|
mapOptions = {
|
||||||
|
center: new google.maps.LatLng(52.23, 21.01),
|
||||||
|
zoom: 8,
|
||||||
|
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
||||||
|
scaleControl: true
|
||||||
|
};
|
||||||
|
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayTrack(xml,update) {
|
||||||
|
altitudes.length = 0;
|
||||||
|
var totalMeters = 0;
|
||||||
|
var totalSeconds = 0;
|
||||||
|
// init polyline
|
||||||
|
var poly = new google.maps.Polyline(polyOptions);
|
||||||
|
poly.setMap(map);
|
||||||
|
var path = poly.getPath();
|
||||||
|
var latlngbounds = new google.maps.LatLngBounds( );
|
||||||
|
var positions = xml.getElementsByTagName('position');
|
||||||
|
var posLen = positions.length;
|
||||||
|
for (var i=0; i<posLen; i++) {
|
||||||
|
var p = parsePosition(positions[i]);
|
||||||
|
totalMeters += p.distance;
|
||||||
|
totalSeconds += p.seconds;
|
||||||
|
p['totalMeters'] = totalMeters;
|
||||||
|
p['totalSeconds'] = totalSeconds;
|
||||||
|
p['coordinates'] = new google.maps.LatLng(p.latitude,p.longitude);
|
||||||
|
// set marker
|
||||||
|
setMarker(p,i,posLen);
|
||||||
|
// update polyline
|
||||||
|
path.push(p.coordinates);
|
||||||
|
latlngbounds.extend(p.coordinates);
|
||||||
|
// save altitudes for chart
|
||||||
|
altitudes[i] = p.altitude;
|
||||||
|
}
|
||||||
|
if (update) {
|
||||||
|
map.fitBounds(latlngbounds);
|
||||||
|
if (i==1) {
|
||||||
|
// only one point, zoom out
|
||||||
|
zListener =
|
||||||
|
google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
|
||||||
|
if (this.getZoom()){
|
||||||
|
this.setZoom(15);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTimeout(function(){google.maps.event.removeListener(zListener)}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
latestTime = p.dateoccured;
|
||||||
|
polies.push(poly);
|
||||||
|
|
||||||
|
updateSummary(p.dateoccured,totalMeters,totalSeconds);
|
||||||
|
if (p.tid!=trackid) {
|
||||||
|
trackid=p.tid;
|
||||||
|
setTrack(trackid);
|
||||||
|
}
|
||||||
|
if (document.getElementById('bottom').style.display=='block') {
|
||||||
|
// update altitudes chart
|
||||||
|
chart.clearChart();
|
||||||
|
displayChart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearMap(){
|
||||||
|
if (polies){
|
||||||
|
for (var i=0; i<polies.length; i++){
|
||||||
|
polies[i].setMap(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (markers){
|
||||||
|
for (var i=0; i<markers.length; i++){
|
||||||
|
google.maps.event.removeListener(popups[i].listener);
|
||||||
|
popups[i].setMap(null);
|
||||||
|
markers[i].setMap(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
markers.length = 0;
|
||||||
|
polies.length = 0;
|
||||||
|
popups.lentgth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var popup;
|
||||||
|
function setMarker(p,i,posLen) {
|
||||||
|
// marker
|
||||||
|
var marker = new google.maps.Marker( {
|
||||||
|
map: map,
|
||||||
|
position: p.coordinates,
|
||||||
|
title: p.dateoccured
|
||||||
|
});
|
||||||
|
if (latest==1) { marker.setIcon('http://maps.google.com/mapfiles/dd-end.png') }
|
||||||
|
else if (i==0) { marker.setIcon('http://maps.google.com/mapfiles/marker_greenA.png') }
|
||||||
|
else if (i==posLen-1) { marker.setIcon('http://maps.google.com/mapfiles/markerB.png') }
|
||||||
|
else { marker.setIcon('http://labs.google.com/ridefinder/images/mm_20_gray.png') }
|
||||||
|
// popup
|
||||||
|
var content = '<div id="popup">'+
|
||||||
|
'<div id="pheader">'+lang_user+': '+p.username.toUpperCase()+'<br />'+lang_track+': '+p.trackname.toUpperCase()+
|
||||||
|
'</div>'+
|
||||||
|
'<div id="pbody">'+
|
||||||
|
'<div id="pleft"><b>'+lang_time+':</b> '+p.dateoccured+'<br />'+
|
||||||
|
((p.speed != null)?'<b>'+lang_speed+':</b> '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'<br />':'')+
|
||||||
|
((p.altitude != null)?'<b>'+lang_altitude+':</b> '+(p.altitude*factor_m).toFixed()+' '+unit_m+'<br />':'')+'</div>'+
|
||||||
|
((latest==0)?
|
||||||
|
('<div id="pright"><b>'+lang_ttime+':</b> '+p.totalSeconds.toHMS()+'<br />'+
|
||||||
|
'<b>'+lang_aspeed+':</b> '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'<br />'+
|
||||||
|
'<b>'+lang_tdistance+':</b> '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'<br />'+'</div>'):'')+
|
||||||
|
'<div id="pfooter">'+lang_point+' '+(i+1)+' '+lang_of+' '+(posLen)+'</div>'+
|
||||||
|
'</div></div>';
|
||||||
|
popup = new google.maps.InfoWindow();
|
||||||
|
popup.listener = google.maps.event.addListener(marker, 'click', (function(marker,content) {
|
||||||
|
return function() {
|
||||||
|
popup.setContent(content);
|
||||||
|
popup.open(map, marker);
|
||||||
|
if (document.getElementById('bottom').style.display=='block') {
|
||||||
|
chart.setSelection([{row:i,column:null}]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(marker,content));
|
||||||
|
markers.push(marker);
|
||||||
|
popups.push(popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addChartEvent(chart) {
|
||||||
|
google.visualization.events.addListener(chart, 'select', function() {
|
||||||
|
if (popup) {popup.close(); clearTimeout(altTimeout);}
|
||||||
|
var selection = chart.getSelection()[0];
|
||||||
|
if (selection) {
|
||||||
|
var id = selection.row;
|
||||||
|
var icon = markers[id].getIcon();
|
||||||
|
markers[id].setIcon('http://maps.google.com/mapfiles/marker_orange.png');
|
||||||
|
//var contentString = '<div style="width:40px; height:20px;padding:10px">'+Math.round(altitudes[id]*factor_m)+' '+unit_m+'</div>';
|
||||||
|
//popup = new google.maps.InfoWindow({
|
||||||
|
// content: contentString
|
||||||
|
//});
|
||||||
|
//popup.open(map,markers[id]);
|
||||||
|
//altTimeout = setTimeout(function() { if (popup) {popup.close();} },2000);
|
||||||
|
altTimeout = setTimeout(function() { markers[id].setIcon(icon); },2000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
169
api_openlayers.js
Executable file
169
api_openlayers.js
Executable file
@ -0,0 +1,169 @@
|
|||||||
|
/* phpTrackme
|
||||||
|
*
|
||||||
|
* Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net)
|
||||||
|
*
|
||||||
|
* This is free software; you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Library General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// openlayers
|
||||||
|
var map;
|
||||||
|
var layerTrack;
|
||||||
|
var layerMarkers;
|
||||||
|
var lineStyle = {strokeColor: '#FF0000', strokeOpacity: 1, strokeWidth: 2};
|
||||||
|
var wgs84;
|
||||||
|
var mercator;
|
||||||
|
var loadedAPI = 'openlayers';
|
||||||
|
function init() {
|
||||||
|
wgs84 = new OpenLayers.Projection('EPSG:4326'); // from WGS 1984
|
||||||
|
mercator = new OpenLayers.Projection('EPSG:900913'); // to Mercator
|
||||||
|
var options = { controls: [
|
||||||
|
new OpenLayers.Control.ArgParser(), // default
|
||||||
|
new OpenLayers.Control.Attribution(), // default
|
||||||
|
new OpenLayers.Control.LayerSwitcher({'ascending':false}),
|
||||||
|
new OpenLayers.Control.Navigation(), // default
|
||||||
|
new OpenLayers.Control.PanZoomBar(),// do we need it?
|
||||||
|
new OpenLayers.Control.ScaleLine()
|
||||||
|
]
|
||||||
|
};
|
||||||
|
map = new OpenLayers.Map('map-canvas', options);
|
||||||
|
map.addLayer(new OpenLayers.Layer.OSM());
|
||||||
|
var position = new OpenLayers.LonLat(21.01,52.23).transform(wgs84, mercator);
|
||||||
|
var zoom = 8;
|
||||||
|
map.setCenter(position, zoom);
|
||||||
|
}
|
||||||
|
function displayTrack(xml,update) {
|
||||||
|
altitudes.length = 0;
|
||||||
|
var totalMeters = 0;
|
||||||
|
var totalSeconds = 0;
|
||||||
|
// init layer
|
||||||
|
layerTrack = new OpenLayers.Layer.Vector( 'Track' );
|
||||||
|
layerMarkers = new OpenLayers.Layer.Markers( 'Markers' );
|
||||||
|
var points = new Array();
|
||||||
|
var latlngbounds = new OpenLayers.Bounds();
|
||||||
|
var positions = xml.getElementsByTagName('position');
|
||||||
|
var posLen = positions.length;
|
||||||
|
for (var i=0; i<posLen; i++) {
|
||||||
|
var p = parsePosition(positions[i]);
|
||||||
|
totalMeters += p.distance;
|
||||||
|
totalSeconds += p.seconds;
|
||||||
|
p['totalMeters'] = totalMeters;
|
||||||
|
p['totalSeconds'] = totalSeconds;
|
||||||
|
// set marker
|
||||||
|
setMarker(p,i,posLen);
|
||||||
|
// update polyline
|
||||||
|
var point = new OpenLayers.Geometry.Point(p.longitude, p.latitude).transform(wgs84,mercator);
|
||||||
|
latlngbounds.extend(point);
|
||||||
|
points.push(point);
|
||||||
|
// save altitudes for chart
|
||||||
|
altitudes[i] = p.altitude;
|
||||||
|
}
|
||||||
|
var lineString = new OpenLayers.Geometry.LineString(points);
|
||||||
|
var lineFeature = new OpenLayers.Feature.Vector(lineString, null, lineStyle);
|
||||||
|
layerTrack.addFeatures([lineFeature]);
|
||||||
|
map.addLayer(layerTrack);
|
||||||
|
map.addLayer(layerMarkers);
|
||||||
|
if (update) {
|
||||||
|
map.zoomToExtent(latlngbounds);
|
||||||
|
if (i==1) {
|
||||||
|
// only one point, zoom out
|
||||||
|
map.zoomOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
latestTime = p.dateoccured;
|
||||||
|
//polies.push(poly);
|
||||||
|
|
||||||
|
updateSummary(p.dateoccured,totalMeters,totalSeconds);
|
||||||
|
if (p.tid!=trackid) {
|
||||||
|
trackid=p.tid;
|
||||||
|
setTrack(trackid);
|
||||||
|
}
|
||||||
|
if (document.getElementById('bottom').style.display=='block') {
|
||||||
|
// update altitudes chart
|
||||||
|
chart.clearChart();
|
||||||
|
displayChart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearMap(){
|
||||||
|
if (layerTrack){
|
||||||
|
layerTrack.removeAllFeatures();
|
||||||
|
}
|
||||||
|
if (layerMarkers){
|
||||||
|
layerMarkers.clearMarkers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMarker(p,i,posLen) {
|
||||||
|
// marker
|
||||||
|
var lonLat = new OpenLayers.LonLat(p.longitude,p.latitude).transform(wgs84,mercator);
|
||||||
|
var size = new OpenLayers.Size(21, 25);
|
||||||
|
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
|
||||||
|
if (latest==1) { var icon = new OpenLayers.Icon('http://www.openstreetmap.org/openlayers/img/marker.png',size,offset); }
|
||||||
|
else if (i==0) { var icon = new OpenLayers.Icon('http://www.openstreetmap.org/openlayers/img/marker-green.png',size,offset); }
|
||||||
|
else if (i==posLen-1) { var icon = new OpenLayers.Icon('http://www.openstreetmap.org/openlayers/img/marker.png',size,offset); }
|
||||||
|
else {
|
||||||
|
size = new OpenLayers.Size(12, 20);
|
||||||
|
offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
|
||||||
|
var icon = new OpenLayers.Icon('http://labs.google.com/ridefinder/images/mm_20_gray.png',size,offset);
|
||||||
|
}
|
||||||
|
var marker = new OpenLayers.Marker(lonLat,icon);
|
||||||
|
layerMarkers.addMarker(marker);
|
||||||
|
|
||||||
|
|
||||||
|
// popup
|
||||||
|
var content = '<div id="popup">'+
|
||||||
|
'<div id="pheader">'+lang_user+': '+p.username.toUpperCase()+'<br />'+lang_track+': '+p.trackname.toUpperCase()+
|
||||||
|
'</div>'+
|
||||||
|
'<div id="pbody">'+
|
||||||
|
'<div id="pleft"><b>'+lang_time+':</b> '+p.dateoccured+'<br />'+
|
||||||
|
((p.speed != null)?'<b>'+lang_speed+':</b> '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'<br />':'')+
|
||||||
|
((p.altitude != null)?'<b>'+lang_altitude+':</b> '+(p.altitude*factor_m).toFixed()+' '+unit_m+'<br />':'')+'</div>'+
|
||||||
|
((latest==0)?
|
||||||
|
('<div id="pright"><b>'+lang_ttime+':</b> '+p.totalSeconds.toHMS()+'<br />'+
|
||||||
|
'<b>'+lang_aspeed+':</b> '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'<br />'+
|
||||||
|
'<b>'+lang_tdistance+':</b> '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'<br />'+'</div>'):'')+
|
||||||
|
'<div id="pfooter">'+lang_point+' '+(i+1)+' '+lang_of+' '+(posLen)+'</div>'+
|
||||||
|
'</div></div>';
|
||||||
|
marker.events.register("mousedown", marker, (function() {
|
||||||
|
return function() {
|
||||||
|
// remove popups
|
||||||
|
if (map.popups.length>0) {
|
||||||
|
for (var i = map.popups.length-1; i>=0; i-- ) {
|
||||||
|
map.removePopup(map.popups[i])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// show popup
|
||||||
|
var popup = new OpenLayers.Popup.FramedCloud("id "+(i+1),lonLat,null,content,icon,true);
|
||||||
|
map.addPopup(popup);
|
||||||
|
if (document.getElementById('bottom').style.display=='block') {
|
||||||
|
chart.setSelection([{row:i,column:null}]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function addChartEvent(chart) {
|
||||||
|
google.visualization.events.addListener(chart, 'select', function() {
|
||||||
|
var selection = chart.getSelection()[0];
|
||||||
|
if (selection) {
|
||||||
|
var id = selection.row;
|
||||||
|
var marker = layerMarkers.markers[id];
|
||||||
|
var url = marker.icon.url;
|
||||||
|
marker.setUrl('http://www.openstreetmap.org/openlayers/img/marker-gold.png');
|
||||||
|
altTimeout = setTimeout(function() { marker.setUrl(url); },2000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
17
config.php
17
config.php
@ -17,15 +17,18 @@
|
|||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
$version = "1.0";
|
$version = "2.0";
|
||||||
|
|
||||||
// map drawing framework
|
// map drawing framework
|
||||||
// (gmaps = google maps, osm = openstreetmap (not supported yet))
|
// (gmaps = google maps, openlayers = openlayers/osm)
|
||||||
$mapapi = "gmaps";
|
$mapapi = "gmaps";
|
||||||
|
//$mapapi = "openlayers";
|
||||||
|
|
||||||
// you may add your google maps api key
|
// you may add your google maps api key
|
||||||
// this is not obligatory by now
|
// this is not obligatory by now
|
||||||
//$gkey =
|
//$gkey =
|
||||||
|
|
||||||
// db
|
// MySQL config
|
||||||
$dbhost = ""; // mysql host, eg. localhost
|
$dbhost = ""; // mysql host, eg. localhost
|
||||||
$dbuser = ""; // database user
|
$dbuser = ""; // database user
|
||||||
$dbpass = ""; // database pass
|
$dbpass = ""; // database pass
|
||||||
@ -35,17 +38,23 @@ $salt = ""; // fill in random string here, it will increase security of password
|
|||||||
// other
|
// other
|
||||||
// require login/password authentication
|
// require login/password authentication
|
||||||
// (0 = no, 1 = yes)
|
// (0 = no, 1 = yes)
|
||||||
$require_authentication = 0;
|
$require_authentication = 1;
|
||||||
|
|
||||||
// allow automatic registration of new users
|
// allow automatic registration of new users
|
||||||
// (0 = no, 1 = yes)
|
// (0 = no, 1 = yes)
|
||||||
$allow_registration = 0;
|
$allow_registration = 0;
|
||||||
|
|
||||||
// Default interval in seconds for live auto reload
|
// Default interval in seconds for live auto reload
|
||||||
$interval = 10;
|
$interval = 10;
|
||||||
|
|
||||||
// Default language
|
// Default language
|
||||||
// (en, pl)
|
// (en, pl)
|
||||||
$lang = "en";
|
$lang = "en";
|
||||||
|
//$lang = "pl";
|
||||||
|
|
||||||
// units
|
// units
|
||||||
// (metric, imperial)
|
// (metric, imperial)
|
||||||
$units = "metric";
|
$units = "metric";
|
||||||
|
//$units = "imperial";
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
64
index.php
64
index.php
@ -67,6 +67,17 @@ $track_form .= '
|
|||||||
</form>
|
</form>
|
||||||
';
|
';
|
||||||
|
|
||||||
|
// map api select form
|
||||||
|
$api_form = '
|
||||||
|
<u>'.$lang_api.'</u><br />
|
||||||
|
<form>
|
||||||
|
<select name="track" onchange="loadMapAPI(this.options[this.selectedIndex].value);">
|
||||||
|
<option value="gmaps"'.(($mapapi=="gmaps")?' selected':'').'>Google Maps</option>
|
||||||
|
<option value="openlayers"'.(($mapapi=="openlayers")?' selected':'').'>OpenLayers</option>
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
';
|
||||||
|
|
||||||
print
|
print
|
||||||
'<!DOCTYPE html>
|
'<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
@ -74,7 +85,7 @@ print
|
|||||||
<title>'.$lang_title.'</title>
|
<title>'.$lang_title.'</title>
|
||||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
||||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||||
<link rel="stylesheet" type="text/css" href="main.css">
|
<link rel="stylesheet" type="text/css" href="main.css" />
|
||||||
<script>
|
<script>
|
||||||
var interval = '.$interval.';
|
var interval = '.$interval.';
|
||||||
var userid = '.(($auth)?$auth:-1).';
|
var userid = '.(($auth)?$auth:-1).';
|
||||||
@ -93,54 +104,20 @@ print
|
|||||||
var lang_track = "'.$lang_track.'";
|
var lang_track = "'.$lang_track.'";
|
||||||
var lang_newinterval = "'.$lang_newinterval.'";
|
var lang_newinterval = "'.$lang_newinterval.'";
|
||||||
var units = "'.$units.'";
|
var units = "'.$units.'";
|
||||||
|
var mapapi = "'.$mapapi.'";
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="main.js">
|
<script type="text/javascript" src="main.js"></script>
|
||||||
</script>
|
|
||||||
';
|
';
|
||||||
if ($mapapi == "gmaps") {
|
if ($mapapi == "gmaps") {
|
||||||
print
|
print
|
||||||
' <script type="text/javascript"
|
' <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?'.(isset($gkey)?'key='.$gkey.'&':'').'sensor=false"></script>
|
||||||
src="https://maps.googleapis.com/maps/api/js?'.(isset($gkey)?'key='.$gkey.'&':'').'sensor=false">
|
<script type="text/javascript" src="api_gmaps.js"></script>
|
||||||
</script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var map;
|
|
||||||
var polies = new Array();
|
|
||||||
var markers = new Array();
|
|
||||||
var popups = new Array();
|
|
||||||
google.maps.visualRefresh = true;
|
|
||||||
var polyOptions = {
|
|
||||||
strokeColor: \'#FF0000\',
|
|
||||||
strokeOpacity: 1.0,
|
|
||||||
strokeWeight: 2
|
|
||||||
}
|
|
||||||
var mapOptions = {
|
|
||||||
center: new google.maps.LatLng(52.23, 21.01),
|
|
||||||
zoom: 8,
|
|
||||||
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
|
||||||
scaleControl: true
|
|
||||||
};
|
|
||||||
function init() {
|
|
||||||
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print
|
print
|
||||||
' <script type="text/javascript"
|
' <script type="text/javascript" src="http://openlayers.org/api/OpenLayers.js"></script>
|
||||||
src="http://openlayers.org/api/OpenLayers.js">
|
<script type="text/javascript" src="api_openlayers.js"></script>
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
function init() {
|
|
||||||
map = new OpenLayers.Map("map-canvas");
|
|
||||||
map.addLayer(new OpenLayers.Layer.OSM());
|
|
||||||
var fromProjection = new OpenLayers.Projection("EPSG:4326"); // Transform from WGS 1984
|
|
||||||
var toProjection = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection
|
|
||||||
var position = new OpenLayers.LonLat(21.01,52.23).transform(fromProjection, toProjection);
|
|
||||||
var zoom = 8;
|
|
||||||
map.setCenter(position, zoom);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
';
|
';
|
||||||
}
|
}
|
||||||
print '
|
print '
|
||||||
@ -163,7 +140,10 @@ print '
|
|||||||
</div>
|
</div>
|
||||||
<div id="summary"></div>
|
<div id="summary"></div>
|
||||||
<div id="other">
|
<div id="other">
|
||||||
<a href="javascript:void(0);" onclick="toggleChart();">'.$lang_chart.'</a><br />
|
<a href="javascript:void(0);" onclick="toggleChart();">'.$lang_chart.'</a>
|
||||||
|
</div>
|
||||||
|
<div id="api">
|
||||||
|
'.$api_form.'
|
||||||
</div>
|
</div>
|
||||||
<div id="export">
|
<div id="export">
|
||||||
<u>'.$lang_download.'</u><br />
|
<u>'.$lang_download.'</u><br />
|
||||||
|
2
lang.php
2
lang.php
@ -47,6 +47,7 @@ switch($lang) {
|
|||||||
$lang_password = "Password";
|
$lang_password = "Password";
|
||||||
$lang_language = "Language";
|
$lang_language = "Language";
|
||||||
$lang_newinterval = "Enter new interval value (seconds)";
|
$lang_newinterval = "Enter new interval value (seconds)";
|
||||||
|
$lang_api = "Map API";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "pl":
|
case "pl":
|
||||||
@ -77,6 +78,7 @@ switch($lang) {
|
|||||||
$lang_password = "Hasło";
|
$lang_password = "Hasło";
|
||||||
$lang_language = "Język";
|
$lang_language = "Język";
|
||||||
$lang_newinterval = "Podaj częstotliwość odświeżania (w sekundach)";
|
$lang_newinterval = "Podaj częstotliwość odświeżania (w sekundach)";
|
||||||
|
$lang_api = "Map API";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
16
main.css
16
main.css
@ -78,7 +78,7 @@ input[type = "checkbox"] {
|
|||||||
background-color: #666;
|
background-color: #666;
|
||||||
color: lightgray;
|
color: lightgray;
|
||||||
}
|
}
|
||||||
#user, #trip, #summary, #export, #other {
|
#user, #trip, #summary, #export, #other, #api {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
#login {
|
#login {
|
||||||
@ -107,8 +107,12 @@ input[type = "checkbox"] {
|
|||||||
color: yellow;
|
color: yellow;
|
||||||
}
|
}
|
||||||
#popup {
|
#popup {
|
||||||
width:350px;
|
width:370px;
|
||||||
height:150px;
|
height:130px;
|
||||||
|
}
|
||||||
|
#popup * {
|
||||||
|
font-family: Roboto, Verdana, sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
#pheader {
|
#pheader {
|
||||||
font-weight: bolder;
|
font-weight: bolder;
|
||||||
@ -129,6 +133,8 @@ input[type = "checkbox"] {
|
|||||||
}
|
}
|
||||||
#bottom {
|
#bottom {
|
||||||
display: none;
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10000;
|
||||||
}
|
}
|
||||||
#chart {
|
#chart {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -139,10 +145,10 @@ input[type = "checkbox"] {
|
|||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
#close {
|
#close {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
bottom: 175px;
|
bottom: 175px;
|
||||||
right: 175px;
|
right: 175px;
|
||||||
z-index: 100;
|
z-index: 10001;
|
||||||
font-family: Verdana, sans-serif;
|
font-family: Verdana, sans-serif;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
194
main.js
194
main.js
@ -16,124 +16,6 @@
|
|||||||
* License along with this program; if not, write to the Free Software
|
* License along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
// google maps
|
|
||||||
function displayTrack(xml,update) {
|
|
||||||
altitudes.length = 0;
|
|
||||||
var totalMeters = 0;
|
|
||||||
var totalSeconds = 0;
|
|
||||||
// init polyline
|
|
||||||
var poly = new google.maps.Polyline(polyOptions);
|
|
||||||
poly.setMap(map);
|
|
||||||
var path = poly.getPath();
|
|
||||||
var latlngbounds = new google.maps.LatLngBounds( );
|
|
||||||
var positions = xml.getElementsByTagName('position');
|
|
||||||
var posLen = positions.length;
|
|
||||||
for (var i=0; i<posLen; i++) {
|
|
||||||
var p = parsePosition(positions[i]);
|
|
||||||
totalMeters += p.distance;
|
|
||||||
totalSeconds += p.seconds;
|
|
||||||
p['totalMeters'] = totalMeters;
|
|
||||||
p['totalSeconds'] = totalSeconds;
|
|
||||||
p['coordinates'] = new google.maps.LatLng(p.latitude,p.longitude);
|
|
||||||
// set marker
|
|
||||||
setMarker(p,i,posLen);
|
|
||||||
// update polyline
|
|
||||||
path.push(p.coordinates);
|
|
||||||
latlngbounds.extend(p.coordinates);
|
|
||||||
// save altitudes for chart
|
|
||||||
altitudes[i] = p.altitude;
|
|
||||||
}
|
|
||||||
if (update) {
|
|
||||||
map.fitBounds(latlngbounds);
|
|
||||||
if (i==1) {
|
|
||||||
// only one point, zoom out
|
|
||||||
zListener =
|
|
||||||
google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
|
|
||||||
if (this.getZoom()){
|
|
||||||
this.setZoom(15);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setTimeout(function(){google.maps.event.removeListener(zListener)}, 2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
latestTime = p.dateoccured;
|
|
||||||
polies.push(poly);
|
|
||||||
|
|
||||||
updateSummary(p.dateoccured,totalMeters,totalSeconds);
|
|
||||||
if (p.tid!=trackid) {
|
|
||||||
trackid=p.tid;
|
|
||||||
setTrack(trackid);
|
|
||||||
}
|
|
||||||
if (document.getElementById('bottom').style.display=='block') {
|
|
||||||
// update altitudes chart
|
|
||||||
chart.clearChart();
|
|
||||||
displayChart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearMap(){
|
|
||||||
if (polies){
|
|
||||||
for (var i=0; i<polies.length; i++){
|
|
||||||
polies[i].setMap(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (markers){
|
|
||||||
for (var i=0; i<markers.length; i++){
|
|
||||||
google.maps.event.removeListener(popups[i].listener);
|
|
||||||
popups[i].setMap(null);
|
|
||||||
markers[i].setMap(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
markers.length = 0;
|
|
||||||
polies.length = 0;
|
|
||||||
popups.lentgth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var popup;
|
|
||||||
function setMarker(p,i,posLen) {
|
|
||||||
// marker
|
|
||||||
var marker = new google.maps.Marker( {
|
|
||||||
map: map,
|
|
||||||
position: p.coordinates,
|
|
||||||
title: p.dateoccured
|
|
||||||
});
|
|
||||||
if (latest==1) { marker.setIcon('http://maps.google.com/mapfiles/dd-end.png') }
|
|
||||||
else if (i==0) { marker.setIcon('http://maps.google.com/mapfiles/marker_greenA.png') }
|
|
||||||
else if (i==posLen-1) { marker.setIcon('http://maps.google.com/mapfiles/markerB.png') }
|
|
||||||
else { marker.setIcon('http://labs.google.com/ridefinder/images/mm_20_gray.png') }
|
|
||||||
// popup
|
|
||||||
var content = '<div id="popup">'+
|
|
||||||
'<div id="pheader">'+lang_user+': '+p.username.toUpperCase()+'<br />'+lang_track+': '+p.trackname.toUpperCase()+
|
|
||||||
'</div>'+
|
|
||||||
'<div id="pbody">'+
|
|
||||||
'<div id="pleft"><b>'+lang_time+':</b> '+p.dateoccured+'<br />'+
|
|
||||||
((p.speed != null)?'<b>'+lang_speed+':</b> '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'<br />':'')+
|
|
||||||
((p.altitude != null)?'<b>'+lang_altitude+':</b> '+(p.altitude*factor_m).toFixed()+' '+unit_m+'<br />':'')+'</div>'+
|
|
||||||
((latest==0)?
|
|
||||||
('<div id="pright"><b>'+lang_ttime+':</b> '+p.totalSeconds.toHMS()+'<br />'+
|
|
||||||
'<b>'+lang_aspeed+':</b> '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'<br />'+
|
|
||||||
'<b>'+lang_tdistance+':</b> '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'<br />'+'</div>'):'')+
|
|
||||||
'<div id="pfooter">'+lang_point+' '+(i+1)+' '+lang_of+' '+(posLen)+'</div>'+
|
|
||||||
'</div></div>';
|
|
||||||
popup = new google.maps.InfoWindow();
|
|
||||||
popup.listener = google.maps.event.addListener(marker, 'click', (function(marker,content) {
|
|
||||||
return function() {
|
|
||||||
popup.setContent(content);
|
|
||||||
popup.open(map, marker);
|
|
||||||
if (document.getElementById('bottom').style.display=='block') {
|
|
||||||
chart.setSelection([{row:i,column:null}]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})(marker,content));
|
|
||||||
markers.push(marker);
|
|
||||||
popups.push(popup);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// openstreetmaps
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
|
|
||||||
// general stuff
|
// general stuff
|
||||||
if (units=='imperial') {
|
if (units=='imperial') {
|
||||||
@ -177,19 +59,7 @@ function displayChart() {
|
|||||||
chart = new google.visualization.LineChart(document.getElementById('chart'));
|
chart = new google.visualization.LineChart(document.getElementById('chart'));
|
||||||
chart.draw(data, options);
|
chart.draw(data, options);
|
||||||
|
|
||||||
google.visualization.events.addListener(chart, 'select', function() {
|
addChartEvent(chart);
|
||||||
if (popup) {popup.close(); clearTimeout(altTimeout);}
|
|
||||||
var selection = chart.getSelection()[0];
|
|
||||||
if (selection) {
|
|
||||||
var id = selection.row;
|
|
||||||
var contentString = '<div style="width:40px; height:20px;padding:10px">'+Math.round(altitudes[id]*factor_m)+' '+unit_m+'</div>';
|
|
||||||
popup = new google.maps.InfoWindow({
|
|
||||||
content: contentString
|
|
||||||
});
|
|
||||||
popup.open(map,markers[id]);
|
|
||||||
altTimeout = setTimeout(function() { if (popup) {popup.close();} },2000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleChart(i) {
|
function toggleChart(i) {
|
||||||
@ -410,3 +280,65 @@ function setTime() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dynamic change of map api
|
||||||
|
function loadMapAPI(api) {
|
||||||
|
document.getElementById("map-canvas").innerHTML = '';
|
||||||
|
var url = new Array();
|
||||||
|
if (api=='gmaps') {
|
||||||
|
url.push('api_gmaps.js');
|
||||||
|
url.push('https://maps.googleapis.com/maps/api/js?sensor=false&callback=init');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
url.push('api_openlayers.js');
|
||||||
|
url.push('http://openlayers.org/api/OpenLayers.js');
|
||||||
|
}
|
||||||
|
addScript(url[0]);
|
||||||
|
waitAndLoad(api,url);
|
||||||
|
}
|
||||||
|
var loadTime = 0;
|
||||||
|
function waitAndLoad(api,url) {
|
||||||
|
// wait till first script loaded
|
||||||
|
if (loadTime>5000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; }
|
||||||
|
if (loadedAPI!==api) {
|
||||||
|
setTimeout(function() { loadTime += 50; waitAndLoad(api,url); }, 50);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!isScriptLoaded(url[1])){
|
||||||
|
addScript(url[1]);
|
||||||
|
}
|
||||||
|
loadTime = 0;
|
||||||
|
waitAndInit(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitAndInit(api) {
|
||||||
|
// wait till main api loads
|
||||||
|
if (loadTime>10000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; }
|
||||||
|
try {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
setTimeout(function() { loadTime += 50; waitAndInit(api); }, 50);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadTime = 0;
|
||||||
|
loadTrack(userid,trackid,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addScript(url) {
|
||||||
|
var tag = document.createElement('script');
|
||||||
|
tag.setAttribute('type','text/javascript');
|
||||||
|
tag.setAttribute('src', url);
|
||||||
|
if (typeof tag!='undefined') {
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isScriptLoaded(url) {
|
||||||
|
scripts = document.getElementsByTagName('script');
|
||||||
|
for (var i = scripts.length; i--;) {
|
||||||
|
// check if url matches src
|
||||||
|
if (scripts[i].src != '' && url.indexOf(scripts[i].src) !== -1) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user