Replace Leaftlet Elevation with HeightGraph
This commit is contained in:
@@ -23,6 +23,7 @@ class Converter extends PhpObject {
|
||||
|
||||
$oGeoJson->buildTracks($oGpx->getTracks());
|
||||
if($oGeoJson->isSimplicationRequired()) $oGeoJson->buildTracks($oGpx->getTracks(), true);
|
||||
$oGeoJson->sortOffTracks();
|
||||
$oGeoJson->saveFile();
|
||||
|
||||
return $oGpx->getLog().'<br />'.$oGeoJson->getLog();
|
||||
@@ -205,6 +206,58 @@ class GeoJson extends Geo {
|
||||
if($bSimplify) $this->addNotice('Total: '.$iGlobalInvalidPointCount.'/'.$iGlobalPointCount.' points removed ('.round($iGlobalInvalidPointCount / $iGlobalPointCount * 100, 1).'%)');
|
||||
}
|
||||
|
||||
|
||||
public function sortOffTracks() {
|
||||
$this->addNotice('Sorting off-tracks');
|
||||
|
||||
//Find first & last track points
|
||||
$asTracksEnds = array();
|
||||
$asTracks = array();
|
||||
foreach($this->asTracks as $iTrackId=>$asTrack) {
|
||||
$sTrackId = 't'.$iTrackId;
|
||||
$asTracksEnds[$sTrackId] = array('first'=>reset($asTrack['geometry']['coordinates']), 'last'=>end($asTrack['geometry']['coordinates']));
|
||||
$asTracks[$sTrackId] = $asTrack;
|
||||
}
|
||||
|
||||
//Find variants close-by tracks
|
||||
$asClonedTracks = $asTracks;
|
||||
foreach($asClonedTracks as $sTrackId=>$asTrack) {
|
||||
if($asTrack['properties']['type'] != 'off-track') continue;
|
||||
|
||||
$iMinDistance = INF;
|
||||
$sConnectedTrackId = 0;
|
||||
$iPosition = 0;
|
||||
|
||||
//Test all track ending points to find the closest
|
||||
foreach($asTracksEnds as $sTrackEndId=>$asTrackEnds) {
|
||||
if($sTrackEndId != $sTrackId) {
|
||||
//Calculate distance between the last point of the track and every starting point of other tracks
|
||||
$iDistance = self::getDistance($asTracksEnds[$sTrackId]['last'], $asTrackEnds['first']);
|
||||
if($iDistance < $iMinDistance) {
|
||||
$sConnectedTrackId = $sTrackEndId;
|
||||
$iPosition = 0; //Track before the Connected Track
|
||||
$iMinDistance = $iDistance;
|
||||
}
|
||||
|
||||
//Calculate distance between the first point of the track and every ending point of other tracks
|
||||
$iDistance = self::getDistance($asTracksEnds[$sTrackId]['first'], $asTrackEnds['last']);
|
||||
if($iDistance < $iMinDistance) {
|
||||
$sConnectedTrackId = $sTrackEndId;
|
||||
$iPosition = +1; //Track after the Connected Track
|
||||
$iMinDistance = $iDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Move track
|
||||
unset($asTracks[$sTrackId]);
|
||||
$iOffset = array_search($sConnectedTrackId, array_keys($asTracks)) + $iPosition;
|
||||
$asTracks = array_slice($asTracks, 0, $iOffset) + array($sTrackId => $asTrack) + array_slice($asTracks, $iOffset);
|
||||
}
|
||||
|
||||
$this->asTracks = array_values($asTracks);
|
||||
}
|
||||
|
||||
private function parseOptions($sComment){
|
||||
$asOptions = array(self::OPT_SIMPLE=>'');
|
||||
foreach(explode("\n", $sComment) as $sLine) {
|
||||
@@ -243,6 +296,21 @@ class GeoJson extends Geo {
|
||||
}
|
||||
|
||||
private function buildGeoJson() {
|
||||
return json_encode(array('features'=>$this->asTracks));
|
||||
return json_encode(array('type'=>'FeatureCollection', 'features'=>$this->asTracks));
|
||||
}
|
||||
|
||||
private static function getDistance($asPointA, $asPointB) {
|
||||
$fLatFrom = $asPointA[1];
|
||||
$fLonFrom = $asPointA[0];
|
||||
$fLatTo = $asPointB[1];
|
||||
$fLonTo = $asPointB[0];
|
||||
|
||||
$fRad = M_PI / 180;
|
||||
|
||||
//Calculate distance from latitude and longitude
|
||||
$fTheta = $fLonFrom - $fLonTo;
|
||||
$fDistance = sin($fLatFrom * $fRad) * sin($fLatTo * $fRad) + cos($fLatFrom * $fRad) * cos($fLatTo * $fRad) * cos($fTheta * $fRad);
|
||||
|
||||
return acos($fDistance) / $fRad * 60 * 1.853;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ save = Save
|
||||
admin_save_success = Saved
|
||||
|
||||
track_main = Main track
|
||||
track_offtrack = Off-track
|
||||
track_off-track = Off-track
|
||||
track_hitchhiking = Hitchhiking
|
||||
track_download = Download GPX Track
|
||||
|
||||
@@ -95,4 +95,10 @@ conf_signature = --François
|
||||
email_update_subject= Spotted!
|
||||
update_preheader = New position received
|
||||
update_title = Message
|
||||
update_latest_news = Latest news:
|
||||
update_latest_news = Latest news:
|
||||
|
||||
distance = Distance
|
||||
elevation = Elevation
|
||||
segment_length = Segment length
|
||||
type = Track Type
|
||||
legend = Legend
|
||||
@@ -6,7 +6,7 @@ save = Sauvegarder
|
||||
admin_save_success = Sauvegardé
|
||||
|
||||
track_main = Trajet principal
|
||||
track_offtrack = Variante
|
||||
track_off-track = Variante
|
||||
track_hitchhiking = Hors rando
|
||||
track_download = Télécharger la trace GPX
|
||||
|
||||
@@ -95,4 +95,10 @@ conf_signature = --François
|
||||
email_update_subject= Nouvelle position reçue
|
||||
update_preheader = Nouvelle position !
|
||||
update_title = Message
|
||||
update_latest_news = Dernières nouvelles :
|
||||
update_latest_news = Dernières nouvelles :
|
||||
|
||||
distance = Distance
|
||||
elevation = Dénivelé
|
||||
segment_length = Taille du segment
|
||||
type = Type de rando
|
||||
legend = Légende
|
||||
@@ -30,11 +30,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="elems">
|
||||
<div id="settings-button"><i class="fa fa-menu fa-fw"></i></div>
|
||||
<div id="post-button"><i class="fa fa-fw"></i></div>
|
||||
<div id="settings-button" class="spot-control"><i class="fa fa-menu fa-fw"></i></div>
|
||||
<div id="post-button" class="spot-control"><i class="fa fa-fw"></i></div>
|
||||
<div id="legend" class="leaflet-control-layers leaflet-control leaflet-control-layers-expanded">
|
||||
<div class="track"><span class="line main"></span><span class="desc">[#]lang:track_main[#]</span></div>
|
||||
<div class="track"><span class="line off-track"></span><span class="desc">[#]lang:track_offtrack[#]</span></div>
|
||||
<div class="track"><span class="line off-track"></span><span class="desc">[#]lang:track_off-track[#]</span></div>
|
||||
<div class="track"><span class="line hitchhiking"></span><span class="desc">[#]lang:track_hitchhiking[#]</span></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -391,21 +391,52 @@ function initSpotMessages(aoMessages, aoTracks, bNoFeed) {
|
||||
oScale = L.control.scale({imperial: false, 'position':'bottomright'}).addTo(oMap);
|
||||
|
||||
//Controls: Elevation
|
||||
if(!isIE() && !isMobile()) {
|
||||
var oElev = L.control.elevation({
|
||||
collapsed: true,
|
||||
position: "bottomright",
|
||||
if(!isMobile()) {
|
||||
var aoElevTracks = {type: 'FeatureCollection', features:[], properties: {summary: 'Elevation'}};
|
||||
var aoLegend = {Elevation: {}};
|
||||
for(var i in aoTracks.features) {
|
||||
if(aoTracks.features[i].properties.type != 'hitchhiking') {
|
||||
//Feature
|
||||
var oTrack = jQuery.extend(true, {}, aoTracks.features[i]);
|
||||
var sType = aoTracks.features[i].properties.type;
|
||||
oTrack.properties.attributeType = sType;
|
||||
aoElevTracks.features.push(oTrack);
|
||||
|
||||
//Legend
|
||||
aoLegend.Elevation[sType] = {text: oSpot.lang('track_'+sType), color: self.tmp(['track-type-styles', sType, 'color'])};
|
||||
}
|
||||
}
|
||||
var oElev = L.control.heightgraph({
|
||||
position: 'bottomright',
|
||||
expand: false,
|
||||
width: getElevWidth(),
|
||||
height: 129,
|
||||
hoverNumber: {
|
||||
decimalsX: 0, //distance (km)
|
||||
decimalsY: 0 //elevation (m)
|
||||
height: 200,
|
||||
margins: {
|
||||
top: 10,
|
||||
right: 30,
|
||||
bottom: 55,
|
||||
left: 50
|
||||
},
|
||||
theme: 'spot-theme',
|
||||
onExpand: function(){$('.leaflet-control-scale').hide();},
|
||||
onCollapse: function(){$('.leaflet-control-scale').show();}
|
||||
}).addTo(oMap);
|
||||
self.tmp('elev', oElev);
|
||||
translation: {
|
||||
distance: oSpot.lang('distance'),
|
||||
elevation: oSpot.lang('elevation'),
|
||||
segment_length: oSpot.lang('segment_length'),
|
||||
type: oSpot.lang('type'),
|
||||
legend: oSpot.lang('legend')
|
||||
},
|
||||
xTicks: 3,
|
||||
yTicks: 2,
|
||||
mappings: aoLegend,
|
||||
highlightStyle: {
|
||||
weight: self.tmp(['track-type-styles', 'main', 'weight']),
|
||||
opacity: 1,
|
||||
color: '#326526'
|
||||
},
|
||||
expandCallback: function(bExpanded){$('.leaflet-control-scale').toggle(!bExpanded);}
|
||||
});
|
||||
oElev.addTo(oMap);
|
||||
oElev.addData([aoElevTracks]);
|
||||
//self.tmp('elev', oElev);
|
||||
}
|
||||
|
||||
//Controls: Tiles (layers): Add & Move to Settings Panel
|
||||
@@ -503,8 +534,6 @@ function initSpotMessages(aoMessages, aoTracks, bNoFeed) {
|
||||
asTrailMarkers.start.remove();
|
||||
asTrailMarkers.end.remove();
|
||||
});
|
||||
|
||||
if(!isIE() && !isMobile()) (oElev.addData.bind(oElev))(feature, oLayer);
|
||||
}
|
||||
}
|
||||
}).addTo(oMap));
|
||||
|
||||
4
script/d3.min.js
vendored
4
script/d3.min.js
vendored
File diff suppressed because one or more lines are too long
826
script/leaflet.min.js
vendored
826
script/leaflet.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -355,13 +355,3 @@ $.prototype.onSwipe = function(fCallBack){
|
||||
fCallBack({x:iDeltaX, y:iDeltaY});
|
||||
});
|
||||
};
|
||||
|
||||
function isIE() {
|
||||
var sUA = window.navigator.userAgent;
|
||||
//IE 10: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)
|
||||
//IE 11: Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
|
||||
//Edge 12 (Spartan): Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0
|
||||
//Edge 13: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586
|
||||
//Edge 18: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363
|
||||
return (sUA.indexOf('MSIE ') > 0 || sUA.indexOf('Trident/') > 0 || sUA.indexOf('Edge/') > 0);
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
}
|
||||
|
||||
@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));
|
||||
filter: drop-shadow(1px 0px 0px rgba(0, 0, 0, $opacity));
|
||||
-webkit-filter: drop-shadow(1px 0px 0px rgba(0, 0, 0, $opacity));
|
||||
}
|
||||
|
||||
/* Common objects */
|
||||
|
||||
@@ -28,9 +28,13 @@ $fa-css-prefix: fa;
|
||||
text-align: center;
|
||||
line-height: 44px;
|
||||
text-decoration: none;
|
||||
color: #999;
|
||||
color: #CCC;
|
||||
background: none;
|
||||
@extend .fa;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
/* Map */
|
||||
|
||||
@@ -10,7 +10,7 @@ $stroke-width-height-focus: 2;
|
||||
$stroke-width-axis : 2;
|
||||
|
||||
@import 'leaflet/leaflet';
|
||||
@import 'leaflet/leaflet_elevation';
|
||||
@import 'leaflet/leaflet_heightgraph';
|
||||
|
||||
/* Leaflet fixes */
|
||||
.leaflet-container {
|
||||
@@ -23,27 +23,72 @@ $stroke-width-axis : 2;
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
/* Leaflet Elevation fixes */
|
||||
.#{$theme} {
|
||||
&.height-focus,
|
||||
&.height-focus.line,
|
||||
&.height-focus-label,
|
||||
&.leaflet-control.elevation .area {
|
||||
@include drop-shadow(0.6);
|
||||
.leaflet-control.spot-control, .leaflet-control .heightgraph-toggle {
|
||||
cursor: pointer;
|
||||
text-shadow: 0px 1px 1px rgba(0,0,0,0.8);
|
||||
width: 44px;
|
||||
text-align: center;
|
||||
|
||||
.fa, .heightgraph-toggle-icon {
|
||||
@extend .control-icon;
|
||||
}
|
||||
|
||||
&.leaflet-control.elevation-collapsed {
|
||||
.background {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.elevation-toggle {
|
||||
@extend .control-icon;
|
||||
@extend .fa-elev-chart;
|
||||
}
|
||||
|
||||
/* Leaflet Heightgraph fixes */
|
||||
|
||||
.legend-text, .tick, .tick text, .focusbox, .height-focus.circle, .height-focus.label, .lineSelection, .horizontalLineText {
|
||||
fill: #333 !important;
|
||||
}
|
||||
|
||||
.axis path, .focusbox rect, .focusLine line, .height-focus.label rect, .height-focus.line, .horizontalLine {
|
||||
stroke: #333 !important;
|
||||
}
|
||||
|
||||
.focusbox rect, .height-focus.label rect {
|
||||
stroke-width: 0;
|
||||
}
|
||||
|
||||
.focusLine line, .focusbox rect, .height-focus.label rect {
|
||||
-webkit-filter: drop-shadow(1px 0px 2px rgba(0, 0, 0, 0.6));
|
||||
filter: drop-shadow(1px 0px 2px rgba(0, 0, 0, 0.6));
|
||||
}
|
||||
|
||||
.height-focus.label rect, .focusbox rect {
|
||||
fill: rgba(255,255,255,.6);
|
||||
}
|
||||
|
||||
.heightgraph.leaflet-control {
|
||||
svg.heightgraph-container {
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
|
||||
.area {
|
||||
@include drop-shadow(0.6);
|
||||
}
|
||||
}
|
||||
|
||||
.details text {
|
||||
text-anchor: middle;
|
||||
.horizontalLine {
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
.heightgraph-toggle {
|
||||
height: 44px;
|
||||
background: none;
|
||||
|
||||
.heightgraph-toggle-icon {
|
||||
@extend .fa-elev-chart;
|
||||
position: static;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
.heightgraph-close-icon {
|
||||
@extend .control-icon;
|
||||
@extend .fa-unsubscribe;
|
||||
color: #333;
|
||||
background: none;
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -192,21 +192,6 @@ $legend-color: $post-color;
|
||||
}
|
||||
}
|
||||
|
||||
#post-button, #settings-button {
|
||||
cursor: pointer;
|
||||
text-shadow: 0px 1px 1px rgba(0,0,0,0.8);
|
||||
width: 44px;
|
||||
text-align: center;
|
||||
|
||||
&:hover .fa {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.fa {
|
||||
color: #CCC;
|
||||
@extend .control-icon;
|
||||
}
|
||||
}
|
||||
#post-button .fa {
|
||||
@extend .fa-post;
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
.#{$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}.height-focus{
|
||||
stroke: $base-color;
|
||||
fill: $base-color;
|
||||
}
|
||||
|
||||
.#{$theme}.height-focus.line{
|
||||
pointer-events: none;
|
||||
stroke-width: $stroke-width-height-focus;
|
||||
}
|
||||
|
||||
.#{$theme}.height-focus-label{
|
||||
text-anchor: middle;
|
||||
fill: $base-color;
|
||||
}
|
||||
|
||||
.#{$theme}.height-focus.circle-lower {
|
||||
|
||||
}
|
||||
148
style/leaflet/_leaflet_heightgraph.scss
Normal file
148
style/leaflet/_leaflet_heightgraph.scss
Normal file
@@ -0,0 +1,148 @@
|
||||
.heightgraph-container {
|
||||
background-color: rgba(250,250,250,.8);
|
||||
border-radius: 10px;
|
||||
display: none;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.heightgraph-toggle {
|
||||
cursor: pointer;
|
||||
box-shadow: 0 1px 7px rgba(0, 0, 0, .4);
|
||||
border-radius: 5px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: #f8f8f9;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.heightgraph-toggle-icon {
|
||||
background: url(img/area-chart.svg) no-repeat center center;
|
||||
background-size: 14px 14px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.heightgraph-close-icon {
|
||||
background: url(img/remove.svg) no-repeat center center;
|
||||
background-size: 14px 14px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.border-top {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.legend-hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.legend-text {
|
||||
fill: #000;
|
||||
font-size: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tick, .tick text {
|
||||
fill: #000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.axis .tick line {
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.axis path {
|
||||
stroke: black;
|
||||
fill: none;
|
||||
stroke-width: 2px;
|
||||
shape-rendering: crispEdges;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.focusbox {
|
||||
display: none;
|
||||
font-size: 10px;
|
||||
fill: #000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.focusbox rect {
|
||||
fill: rgba(255, 255, 255, 0.8);
|
||||
stroke-width: 1px;
|
||||
stroke: #888;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.focusbox text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.focusLine line {
|
||||
stroke-width: 1px;
|
||||
stroke: rgb(20, 20, 20);
|
||||
display: none;
|
||||
cursor: default;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.height-focus.label rect {
|
||||
fill: rgba(255, 255, 255, 0.5);
|
||||
stroke-width: 1px;
|
||||
stroke: #888;
|
||||
pointer-events: none;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.height-focus.line {
|
||||
stroke: rgb(20, 20, 20);
|
||||
stroke-width: 1px;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.height-focus.circle {
|
||||
stroke: #FFF;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
.mouse-height-box-text{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.grid .tick {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.grid .tick line {
|
||||
stroke: #EEE;
|
||||
stroke-width: 1px;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.grid path {
|
||||
stroke-width: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.tspan {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.select-symbol {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.select-info {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.lineSelection {
|
||||
cursor: move;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user