Adding elevation chart

This commit is contained in:
2019-02-14 22:59:32 +01:00
parent 34a7cf6b08
commit 299e4c8a54
14 changed files with 1001 additions and 92 deletions

View File

@@ -5,19 +5,12 @@ class Converter extends PhpObject {
const GPX_EXT = '.gpx'; const GPX_EXT = '.gpx';
const GEO_EXT = '.geojson'; const GEO_EXT = '.geojson';
/** public function __construct() {
* Project to convert
* @var Project
*/
private $oProject;
public function __construct(&$oProject) {
parent::__construct(__CLASS__, Settings::DEBUG); parent::__construct(__CLASS__, Settings::DEBUG);
$this->oProject = &$oProject;
} }
public function convertToGeoJson() { public function convertToGeoJson($sGeoFile) {
$sFileName = pathinfo($this->oProject->getGeoFile(), PATHINFO_FILENAME); $sFileName = pathinfo($sGeoFile, PATHINFO_FILENAME);
$sGpxFileName = $sFileName.self::GPX_EXT; $sGpxFileName = $sFileName.self::GPX_EXT;
$sGeoJsonFileName = $sFileName.self::GEO_EXT; $sGeoJsonFileName = $sFileName.self::GEO_EXT;
@@ -70,7 +63,7 @@ class Gpx extends Geo {
$asTrack['points'][] = array( $asTrack['points'][] = array(
'lon' => (float) $asPoint['lon'], 'lon' => (float) $asPoint['lon'],
'lat' => (float) $asPoint['lat'], 'lat' => (float) $asPoint['lat'],
//'ele' => (int) $asPoint->ele 'ele' => (int) $asPoint->ele
); );
} }
} }
@@ -96,7 +89,7 @@ class GeoJson extends Geo {
} }
private function getGeoJson() { private function getGeoJson() {
$asTracks = array(); $asTracks = array('features'=>array());
foreach($this->asTracks as $asTrackProps) { foreach($this->asTracks as $asTrackProps) {
switch($asTrackProps['color']) { switch($asTrackProps['color']) {
@@ -114,15 +107,15 @@ class GeoJson extends Geo {
'description' => $asTrackProps['desc'] 'description' => $asTrackProps['desc']
), ),
'geometry' => array( 'geometry' => array(
'type' => 'MultiLineString', 'type' => 'LineString',
'coordinates' => array() 'coordinates' => array()
) )
); );
foreach($asTrackProps['points'] as $asPoint) { foreach($asTrackProps['points'] as $asPoint) {
$asTrack['geometry']['coordinates'][0][] = array_values($asPoint); $asTrack['geometry']['coordinates'][] = array_values($asPoint);
} }
$asTracks[] = $asTrack; $asTracks['features'][] = $asTrack;
} }
return $asTracks; return $asTracks;

View File

@@ -100,7 +100,13 @@ class Project extends PhpObject {
case 1: $asProject['mode'] = self::MODE_BLOG; break; case 1: $asProject['mode'] = self::MODE_BLOG; break;
case 2: $asProject['mode'] = self::MODE_HISTO; break; case 2: $asProject['mode'] = self::MODE_HISTO; break;
} }
$asProject['geofile'] = Spot::addTimestampToFilePath(self::GEO_FOLDER.$asProject['geofile']);
$sGeoFile = self::GEO_FOLDER.$asProject['geofile'];
if(!file_exists($sGeoFile)) {
(new Converter())->convertToGeoJson($asProject['geofile']);
}
$asProject['geofile'] = Spot::addTimestampToFilePath($sGeoFile);
$asProject['codename'] = $sCodeName; $asProject['codename'] = $sCodeName;
$asProject['timezone_desc'] = Spot::getTimeZoneDesc($asProject['timezone']); $asProject['timezone_desc'] = Spot::getTimeZoneDesc($asProject['timezone']);
} }

View File

@@ -48,7 +48,8 @@ class Spot extends Main
$asClasses = array( $asClasses = array(
array('name'=>'project', 'project'=>true), array('name'=>'project', 'project'=>true),
array('name'=>'picture', 'project'=>true), array('name'=>'picture', 'project'=>true),
array('name'=>'cacher', 'project'=>true) array('name'=>'cacher', 'project'=>true),
array('name'=>'converter', 'project'=>true)
); );
parent::__construct($oClassManagement, $sProcessPage, $asClasses); parent::__construct($oClassManagement, $sProcessPage, $asClasses);
@@ -140,6 +141,7 @@ class Spot extends Main
'index', 'index',
array( array(
'filepath_css' => self::addTimestampToFilePath('style/spot.css'), 'filepath_css' => self::addTimestampToFilePath('style/spot.css'),
'filepath_js_d3' => self::addTimestampToFilePath('script/d3.min.js'),
'filepath_js_leaflet' => self::addTimestampToFilePath('script/leaflet.min.js'), 'filepath_js_leaflet' => self::addTimestampToFilePath('script/leaflet.min.js'),
'filepath_js_jquery' => self::addTimestampToFilePath('script/jquery.min.js'), 'filepath_js_jquery' => self::addTimestampToFilePath('script/jquery.min.js'),
'filepath_js_jquery_mods' => self::addTimestampToFilePath('script/jquery.mods.js'), 'filepath_js_jquery_mods' => self::addTimestampToFilePath('script/jquery.mods.js'),
@@ -436,6 +438,10 @@ class Spot extends Main
$sToken = Settings::IGN_FR_KEY; $sToken = Settings::IGN_FR_KEY;
$sReferer = 'https://www.visugpx.com/yfJDwfuTlf'; $sReferer = 'https://www.visugpx.com/yfJDwfuTlf';
break; break;
case 'opentopomap':
$sPattern = 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png';
$asDomains = array('a', 'b', 'c');
break;
case 'static': case 'static':
$sPattern = 'https://api.mapbox.com/v4/mapbox.satellite/url-https%3A%2F%2Fspot.lutran.fr%2Fimages%2Ffootprint_mapbox.png({x},{y})/{x},{y},{z}/400x300.png?access_token={token}'; $sPattern = 'https://api.mapbox.com/v4/mapbox.satellite/url-https%3A%2F%2Fspot.lutran.fr%2Fimages%2Ffootprint_mapbox.png({x},{y})/{x},{y},{z}/400x300.png?access_token={token}';
$sToken = Settings::MAPBOX_KEY; $sToken = Settings::MAPBOX_KEY;
@@ -455,9 +461,8 @@ class Spot extends Main
} }
public function convertGpxToGeoJson() { public function convertGpxToGeoJson() {
$this->oClassManagement->incClass('converter', true); $oConverter = new Converter();
$oConverter = new Converter($this->oProject); return $oConverter->convertToGeoJson($this->oProject->getGeoFile());
return $oConverter->convertToGeoJson();
} }
public static function DecToDMS($dValue, $sType='lat') { public static function DecToDMS($dValue, $sType='lat') {

View File

@@ -5,6 +5,7 @@
<link type="image/x-icon" href="images/favicon.ico" rel="shortcut icon" /> <link type="image/x-icon" href="images/favicon.ico" rel="shortcut icon" />
<link type="image/png" href="images/favicon.png" rel="icon" sizes="32x32" /> <link type="image/png" href="images/favicon.png" rel="icon" sizes="32x32" />
<link type="text/css" href="[#]filepath_css[#]" rel="stylesheet" media="all" /> <link type="text/css" href="[#]filepath_css[#]" rel="stylesheet" media="all" />
<script type="text/javascript" src="[#]filepath_js_d3[#]"></script>
<script type="text/javascript" src="[#]filepath_js_leaflet[#]"></script> <script type="text/javascript" src="[#]filepath_js_leaflet[#]"></script>
<script type="text/javascript" src="[#]filepath_js_jquery[#]"></script> <script type="text/javascript" src="[#]filepath_js_jquery[#]"></script>
<script type="text/javascript" src="[#]filepath_js_jquery_mods[#]"></script> <script type="text/javascript" src="[#]filepath_js_jquery_mods[#]"></script>

View File

@@ -137,8 +137,7 @@ function initSpotMessages(aoMessages, aoTracks) {
//Tile layers //Tile layers
var oMapBoxSat = L.tileLayer(self.tmp('tile_api'), {id: 'mapbox.satellite', minZoom: 0, maxZoom: 19}), var oMapBoxSat = L.tileLayer(self.tmp('tile_api'), {id: 'mapbox.satellite', minZoom: 0, maxZoom: 19}),
oOpenTopoMap = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {id: 'OpenTopoMap', minZoom: 2, maxZoom: 19}), oOpenTopoMap = L.tileLayer(self.tmp('tile_api'), {id: 'opentopomap', minZoom: 2, maxZoom: 19}),
//oMapBoxStreet = L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token='+self.vars('mapbox_key'), {id: 'mapbox.streets'}),
oIgnSpain = L.tileLayer(self.tmp('tile_api'), {id: 'ign.es', minZoom: 1, maxZoom: 20}), oIgnSpain = L.tileLayer(self.tmp('tile_api'), {id: 'ign.es', minZoom: 1, maxZoom: 20}),
oIgnFrance = L.tileLayer(self.tmp('tile_api'), {id: 'ign.fr', minZoom: 0, maxZoom: 18, tileSize: 256}), oIgnFrance = L.tileLayer(self.tmp('tile_api'), {id: 'ign.fr', minZoom: 0, maxZoom: 18, tileSize: 256}),
oLinz = L.tileLayer(self.tmp('tile_api'), {id: 'linz', maxZoom: 17, continuousWorld: true, attribution: 'Sourced from LINZ. CC BY 4.0'}); oLinz = L.tileLayer(self.tmp('tile_api'), {id: 'linz', maxZoom: 17, continuousWorld: true, attribution: 'Sourced from LINZ. CC BY 4.0'});
@@ -151,12 +150,71 @@ function initSpotMessages(aoMessages, aoTracks) {
}); });
self.tmp('map', oMap); self.tmp('map', oMap);
//Controls: Legend
var oLegend = L.control({position: 'bottomleft'});
oLegend.onAdd = function(oMap) {return $('#legend').clone()[0];};
oLegend.addTo(oMap);
//Controls: Projects
var oProjects = L.control({position: 'bottomleft'});
oProjects.onAdd = function(oMap) {
var $Labels = $('<div>', {'class': 'leaflet-control-layers-base'});
$.each(self.vars('projects'), function(sCodeName, asProject){
var asRadioAttrs = {'type': 'radio', 'class': 'leaflet-control-layers-selector', 'name':'project', 'value': sCodeName};
if(asProject.id == self.vars(['project', 'id'])) asRadioAttrs.checked = 'checked';
var $Radio =$('<input>', asRadioAttrs).change(function(){
self.setHash(self.vars('page'), [$(this).val()]);
});
var $Label = $('<label>').append($('<div>')
.append($Radio)
.append($('<span>').text(' '+asProject.name))
);
$Labels.append($Label);
});
return $('<div>', {'class':'leaflet-control-layers leaflet-control leaflet-control-layers-expanded'}).append($('<section>').append($Labels))[0];
};
oProjects.addTo(oMap);
//Controls: Scale
oScale = L.control.scale({imperial: false, 'position':'bottomright'}).addTo(oMap);
//Controls: Elevation
var oElev = L.control.elevation({
collapsed: true,
position: "bottomright",
width: $('#messages').width() - $('#feed').outerWidth(true) - $('.leaflet-bottom.leaflet-left').outerWidth(true) + 4,
height: 125,
hoverNumber: {
decimalsX: 0, //distance (km)
decimalsY: 0 //elevation (m)
},
theme: 'spot-theme',
onExpand: function(){$('.leaflet-control-scale').hide();},
onCollapse: function(){$('.leaflet-control-scale').show();}
}).addTo(oMap);
//Controls: Tiles
L.control.layers(
{
'Satellite': oMapBoxSat,
'Open Topo Map': oOpenTopoMap,
'IGN (France)': oIgnFrance,
'IGN (Espagne)': oIgnSpain,
'LINZ (Nouvelle-Zélande)': oLinz
},
null,
{position: 'topleft'}
).addTo(oMap);
//Tracks, colors & popup //Tracks, colors & popup
var oTracks = L.geoJson(aoTracks, { var oTracks = L.geoJson(aoTracks, {
style: function(oTrack) { style: function(oTrack) {
return self.tmp(['track-type-styles', oTrack.properties.type]); return self.tmp(['track-type-styles', oTrack.properties.type]);
}, },
onEachFeature: function (feature, oLayer) { onEachFeature: function(feature, oLayer) {
var asProperties = feature.properties; var asProperties = feature.properties;
var $Tooltip = $('<div>', {'class':'track_tooltip'}); var $Tooltip = $('<div>', {'class':'track_tooltip'});
$('<p>', {'class':'name'}).addIcon('fa-track-'+asProperties.type, true).append(asProperties.name).appendTo($Tooltip); $('<p>', {'class':'name'}).addIcon('fa-track-'+asProperties.type, true).append(asProperties.name).appendTo($Tooltip);
@@ -171,6 +229,8 @@ function initSpotMessages(aoMessages, aoTracks) {
.on('mouseout', function(e) { .on('mouseout', function(e) {
e.target.closePopup(); e.target.closePopup();
}); });
if(asProperties.type != 'hitchhiking') (oElev.addData.bind(oElev))(feature, oLayer);
} }
}).addTo(oMap); }).addTo(oMap);
@@ -186,19 +246,6 @@ function initSpotMessages(aoMessages, aoTracks) {
} }
else oMap.fitBounds(oTracks.getBounds(), {paddingTopLeft: L.point(5, 42), paddingBottomRight: L.point(self.tmp('feed_width')+5, 5)}); else oMap.fitBounds(oTracks.getBounds(), {paddingTopLeft: L.point(5, 42), paddingBottomRight: L.point(self.tmp('feed_width')+5, 5)});
//Controls
L.control.layers(
{
'Satellite': oMapBoxSat,
'Open Topo Map': oOpenTopoMap,
'IGN (France)': oIgnFrance,
'IGN (Espagne)': oIgnSpain,
'LINZ (Nouvelle-Zélande)': oLinz
},
null,
{position: 'topleft'}
).addTo(oMap);
//Building messages //Building messages
$.each(aoMessages, function(iKey, oMsg){ $.each(aoMessages, function(iKey, oMsg){
@@ -213,19 +260,6 @@ function initSpotMessages(aoMessages, aoTracks) {
}) })
}).addTo(oMap); }).addTo(oMap);
//Marker events
/*oMarker.on({
mouseover: function(){
this.openPopup();
},
mouseout: function(){
},
click: function(oPoint){
self.tmp('map').setOffsetView(self.tmp('map_offset'), oPoint.latlng, 15);
}
});*/
//Tooltip //Tooltip
$Tooltip = $('<div>', {'class':'info-window'}) $Tooltip = $('<div>', {'class':'info-window'})
.append($('<h1>') .append($('<h1>')
@@ -258,37 +292,6 @@ function initSpotMessages(aoMessages, aoTracks) {
oSpot.tmp(['markers', oMsg.id_message], oMarker); oSpot.tmp(['markers', oMsg.id_message], oMarker);
}); });
//Legend
var oLegend = L.control({position: 'bottomleft'});
oLegend.onAdd = function(oMap) {return $('#legend').clone()[0];};
oLegend.addTo(oMap);
//Projects
var oProjects = L.control({position: 'bottomleft'});
oProjects.onAdd = function(oMap) {
var $Labels = $('<div>', {'class': 'leaflet-control-layers-base'});
$.each(self.vars('projects'), function(sCodeName, asProject){
var asRadioAttrs = {'type': 'radio', 'class': 'leaflet-control-layers-selector', 'name':'project', 'value': sCodeName};
if(asProject.id == self.vars(['project', 'id'])) asRadioAttrs.checked = 'checked';
var $Radio =$('<input>', asRadioAttrs).change(function(){
self.setHash(self.vars('page'), [$(this).val()]);
});
var $Label = $('<label>').append($('<div>')
.append($Radio)
.append($('<span>').text(' '+asProject.name))
);
$Labels.append($Label);
});
return $('<div>', {'class':'leaflet-control-layers leaflet-control leaflet-control-layers-expanded'}).append($('<section>').append($Labels))[0];
};
oProjects.addTo(oMap);
//Scale
L.control.scale({imperial: false, 'position':'bottomright'}).addTo(oMap);
} }
function getBoundsZoomLevel(bounds, mapDim) { function getBoundsZoomLevel(bounds, mapDim) {

2
script/d3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

795
script/leaflet.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -28,6 +28,19 @@
@include animate(fadeIn 0.8s infinite alternate); @include animate(fadeIn 0.8s infinite alternate);
} }
@mixin rounded($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
-ms-border-radius: $radius;
-o-border-radius: $radius;
border-radius: $radius;
}
@mixin drop-shadow($opacity) {
filter: drop-shadow( -1px 1px 1px rgba(0, 0, 0, $opacity));
-webkit-filter: drop-shadow( -1px 1px 1px rgba(0, 0, 0, $opacity));
}
/* Fonts */ /* Fonts */
@import url('https://fonts.googleapis.com/css?family=Ubuntu:400,700&subset=latin-ext'); @import url('https://fonts.googleapis.com/css?family=Ubuntu:400,700&subset=latin-ext');

View File

@@ -20,6 +20,16 @@ $fa-css-prefix: fa;
} }
} }
.control-icon {
font-size: 28px;
text-align: center;
line-height: 44px;
text-decoration: none;
color: #999;
background: none;
@extend .fa;
}
.#{$fa-css-prefix}-post:before { content: fa-content($fa-var-comment); } .#{$fa-css-prefix}-post:before { content: fa-content($fa-var-comment); }
.#{$fa-css-prefix}-poster:before { content: fa-content($fa-var-comment-edit); } .#{$fa-css-prefix}-poster:before { content: fa-content($fa-var-comment-edit); }
.#{$fa-css-prefix}-message:before { content: fa-content($fa-var-compass); } .#{$fa-css-prefix}-message:before { content: fa-content($fa-var-compass); }
@@ -33,3 +43,5 @@ $fa-css-prefix: fa;
.#{$fa-css-prefix}-track-main:before { content: fa-content($fa-var-hiking); } .#{$fa-css-prefix}-track-main:before { content: fa-content($fa-var-hiking); }
.#{$fa-css-prefix}-track-hitchhiking:before { content: fa-content($fa-var-car-side); } .#{$fa-css-prefix}-track-hitchhiking:before { content: fa-content($fa-var-car-side); }
.#{$fa-css-prefix}-layers:before { content: fa-content($fa-var-layer-group); } .#{$fa-css-prefix}-layers:before { content: fa-content($fa-var-layer-group); }
.#{$fa-css-prefix}-elevation:before { content: fa-content($fa-var-chart-area); }

View File

@@ -0,0 +1,86 @@
$theme : "spot-theme";
$base-color : #CCC;
$highlight-color : #FFF;
$background : rgba($base-color, 0.2);
$drag-color : rgba($highlight-color, 0.2);
$axis-color : darken($base-color,20%);
$stroke-color : darken($base-color,40%);
$stroke-width-mouse-focus : 1;
$stroke-width-height-focus: 2;
$stroke-width-axis : 2;
.#{$theme}.leaflet-control.elevation {
.background {
//background-color: $background;
//@include rounded(3px);
margin: 6px 0 -12px;
}
.axis path,
.axis line {
fill: none;
stroke: $axis-color;
stroke-width: $stroke-width-axis;
}
//.mouse-focus-label-y,
.mouse-focus-label-x {
text-anchor: middle;
}
.mouse-drag{
fill: $drag-color;
}
.elevation-toggle {
cursor: pointer;
width: 44px;
height: 44px;
color: #CCC;
text-shadow: 0px 1px 1px rgba(0,0,0,0.8);
}
.area {
fill: $base-color;
@include drop-shadow(0.6);
}
.mouse-focus-line {
pointer-events: none;
stroke-width: $stroke-width-mouse-focus;
stroke: $stroke-color;
}
}
.#{$theme}.leaflet-control.elevation-collapsed {
.background {
display: none;
}
.elevation-toggle {
@extend .control-icon;
@extend .fa-elevation;
}
}
.#{$theme}.height-focus{
stroke: $base-color;
fill: $base-color;
@include drop-shadow(0.6);
}
.#{$theme}.height-focus.line{
pointer-events: none;
stroke-width: $stroke-width-height-focus;
@include drop-shadow(0.6);
}
.#{$theme}.height-focus-label{
text-anchor: middle;
fill: $base-color;
@include drop-shadow(0.6);
}
.#{$theme}.height-focus.circle-lower {
}

View File

@@ -68,15 +68,9 @@
/* Replace Layers image with font awesome icon */ /* Replace Layers image with font awesome icon */
.leaflet-control-layers-toggle { .leaflet-control-layers-toggle {
font-size: 28px; @extend .control-icon;
text-align: center;
line-height: 44px;
text-decoration: none;
color: #999;
text-shadow: 0px 1px 1px rgba(0,0,0,0.8);
background: none;
@extend .fa;
@extend .fa-layers; @extend .fa-layers;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.8);
} }
.leaflet-control-layers-expanded .leaflet-control-layers-toggle { .leaflet-control-layers-expanded .leaflet-control-layers-toggle {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -6,6 +6,7 @@
/* Site Global CSS */ /* Site Global CSS */
@import 'common'; @import 'common';
@import 'leaflet_elevation';
/* Pages Specific CSS (masks) */ /* Pages Specific CSS (masks) */
@import 'mask_project'; @import 'mask_project';