initial commit
This commit is contained in:
parent
37980ff82b
commit
4cc16bccd0
17 changed files with 789 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
bower_components/
|
||||
nbproject/
|
||||
|
||||
16
bower.json
Normal file
16
bower.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "brouter-web",
|
||||
"version": "0.1.0",
|
||||
"main": "js/index.js",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"bower_components"
|
||||
],
|
||||
"dependencies": {
|
||||
"normalize-css": "*",
|
||||
"leaflet-gpx": "mpetazzoni/leaflet-gpx",
|
||||
"leaflet-search": "*",
|
||||
"leaflet-plugins": "*",
|
||||
"leaflet-routing": "Turistforeningen/leaflet-routing#gh-pages"
|
||||
}
|
||||
}
|
||||
5
css/leaflet-routing.css
Normal file
5
css/leaflet-routing.css
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
div.line-mouse-marker {
|
||||
background-color: #ffffff;
|
||||
border: 2px solid black;
|
||||
border-radius: 10px;
|
||||
}
|
||||
125
css/style.css
Normal file
125
css/style.css
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
html, body, #map {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.info {
|
||||
padding: 6px 8px;
|
||||
font: 14px/16px "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
box-shadow: 0px 0px 0px 3px rgba(70,130,180,0.2), 0 1px 5px rgba(0,0,0,0.4);
|
||||
background: rgba(255,255,255,0.9);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control.elevation .background {
|
||||
box-shadow: 0px 0px 0px 3px rgba(70,130,180,0.2);
|
||||
}
|
||||
div.elevation {
|
||||
margin-bottom: -2px !important;
|
||||
}
|
||||
/*
|
||||
.info, div.elevation {
|
||||
display:table-row;
|
||||
}
|
||||
*/
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#message {
|
||||
position: absolute;
|
||||
left: 446px; /* 400 + 10 + 26 + 10 */
|
||||
top: 0px;
|
||||
margin-top: 10px;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
#header {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
#header, .heading {
|
||||
color: #333;
|
||||
}
|
||||
.title {
|
||||
padding-top: 4px;
|
||||
}
|
||||
.title-name {
|
||||
font-size: larger;
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.4);
|
||||
}
|
||||
.version {
|
||||
font-size: x-small;
|
||||
}
|
||||
.header-text {
|
||||
font-size: small;
|
||||
margin-top: 0.5em;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
.hint {
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-weight: bold;
|
||||
}
|
||||
.heading, .content, .content > .label, .content > .value {
|
||||
float: left;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 4px;
|
||||
/* spacing between cells only */
|
||||
margin: -4px;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top;
|
||||
padding: 0;
|
||||
}
|
||||
#stats td:nth-child(2) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.heading, tr > td:first-child, .label {
|
||||
/* 1/4 of net info control width (370), so that values start at 50% */
|
||||
width: 92.5px;
|
||||
}
|
||||
|
||||
.leaflet-container {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
/* left sidebar as additional control position */
|
||||
|
||||
.leaflet-left {
|
||||
left: 400px !important;
|
||||
}
|
||||
|
||||
.leaflet-leftpane {
|
||||
left: 5px;
|
||||
top: 7px;
|
||||
bottom: 7px;
|
||||
|
||||
/*
|
||||
height: 100%;
|
||||
display:table;
|
||||
*/
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.leaflet-leftpane .leaflet-control {
|
||||
margin: 3px 5px;
|
||||
width: 370px;
|
||||
}
|
||||
|
||||
/* TODO hack to maximize last div, further table-row tests, check out flex box */
|
||||
.leaflet-leftpane .leaflet-control:last-child {
|
||||
position: absolute;
|
||||
top: 432px;
|
||||
bottom: 0px;
|
||||
}
|
||||
100
index.html
Normal file
100
index.html
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>BRouter desktop web client</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<link rel="stylesheet" href="http://leaflet.github.io/Leaflet.draw/leaflet.draw.css" />
|
||||
<!--[if lte IE 8]>
|
||||
<link rel="stylesheet" href="leaflet.draw.ie.css" />
|
||||
<![endif]-->
|
||||
<link rel="stylesheet" href="http://mrmufflon.github.io/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.1.css" />
|
||||
<link rel="stylesheet" href="bower_components/leaflet-search/dist/leaflet-search.min.css" />
|
||||
<link rel="stylesheet" href="css/leaflet-routing.css" />
|
||||
<link rel="stylesheet" href="bower_components/normalize-css/normalize.css" />
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
|
||||
<div id="message" class="info hidden">
|
||||
<span class="hint">Requires a local desktop installation of BRouter</span><br>
|
||||
</div>
|
||||
<div id="header" class="hidden">
|
||||
<div class="title"><span class="title-name">BRouter web</span> <sup class="version">alpha1</sup></div>
|
||||
<div class="header-text">
|
||||
'ESC' to cancel drawing, 'M' to enable drawing<br>
|
||||
Web client for <a href="http://dr-brenschede.de/brouter/" target="_blank">BRouter</a> ·
|
||||
<a href="" target="_blank">about</a> · <a href="" target="_blank">GitHub</a> · <a href="" target="_blank">contact</a><br>
|
||||
</div>
|
||||
</div>
|
||||
<div id="route_options" class="hidden">
|
||||
<table>
|
||||
<tr><td>Profile:</td>
|
||||
<td><select id="profile">
|
||||
<!-- sample profiles -->
|
||||
<option value="trekking">trekking</option>
|
||||
<option value="fastbike">fastbike</option>
|
||||
<option value="safety">safety</option>
|
||||
<option value="shortest">shortest</option>
|
||||
<option value="trekking-ignore-cr">trekking-ignore-cr</option>
|
||||
<option value="trekking-steep">trekking-steep</option>
|
||||
<option value="trekking-noferries">trekking-noferries</option>
|
||||
<option value="trekking-nosteps">trekking-nosteps</option>
|
||||
<option value="moped">moped</option>
|
||||
<option value="car-test">car-test</option>
|
||||
</select></td></tr>
|
||||
<tr><td>Alternative:</td>
|
||||
<td><select id="alternative">
|
||||
<option value="0">original</option>
|
||||
<option value="1">first alternative</option>
|
||||
<option value="2">second alternative</option>
|
||||
<option value="3">third alternative</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
|
||||
<script src="http://leaflet.github.io/Leaflet.draw/leaflet.draw-src.js"></script>
|
||||
<script src="bower_components/leaflet-gpx/gpx.js"></script>
|
||||
<!--
|
||||
<script src="lib/spin.min.js"></script>
|
||||
<script src="lib/leaflet.spin.js"></script>
|
||||
-->
|
||||
<script src="bower_components/leaflet-search/dist/leaflet-search.min.js"></script>
|
||||
<script src="bower_components/leaflet-plugins/control/Permalink.js"></script>
|
||||
<script src="bower_components/leaflet-plugins/control/Permalink.Layer.js"></script>
|
||||
|
||||
<script src="bower_components/leaflet-routing/src/utils/LineUtil.Snapping.js"></script>
|
||||
<script src="bower_components/leaflet-routing/src/utils/Marker.Snapping.js"></script>
|
||||
<script src="bower_components/leaflet-routing/src/L.Routing.js"></script>
|
||||
<script src="bower_components/leaflet-routing/src/L.Routing.Storage.js"></script>
|
||||
<script src="bower_components/leaflet-routing/src/L.Routing.Draw.js"></script>
|
||||
<script src="bower_components/leaflet-routing/src/L.Routing.Edit.js"></script>
|
||||
|
||||
<!--<script src="http://d3js.org/d3.v3.min.js"></script>-->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.1/d3.min.js"></script>
|
||||
<script src="http://mrmufflon.github.io/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.1.min.js"></script>
|
||||
|
||||
<script>
|
||||
// global package prefix for BRouter web application
|
||||
BR = {};
|
||||
</script>
|
||||
<script src="js/router/BRouter.js"></script>
|
||||
<!-- <script src="js/router/brouterCgi.js"></script> -->
|
||||
<script src="js/control/Control.js"></script>
|
||||
<script src="js/plugin/Routing.js"></script>
|
||||
<script src="js/plugin/NogoAreas.js"></script>
|
||||
<script src="js/plugin/Elevation.js"></script>
|
||||
<script src="js/plugin/Search.js"></script>
|
||||
<script src="js/control/TrackStats.js"></script>
|
||||
<script src="js/control/Download.js"></script>
|
||||
<script src="js/control/Profile.js"></script>
|
||||
<script src="js/control/RoutingOptions.js"></script>
|
||||
|
||||
<script src="js/index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
37
js/control/Control.js
Normal file
37
js/control/Control.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
BR.Control = L.Control.extend({
|
||||
options: {
|
||||
position: 'leftpane'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'info'),
|
||||
heading,
|
||||
div;
|
||||
|
||||
if (this.options.heading) {
|
||||
heading = L.DomUtil.create('div', 'heading', container);
|
||||
heading.innerHTML = this.options.heading;
|
||||
this._content = L.DomUtil.create('div', 'content', container);
|
||||
} else {
|
||||
this._content = container;
|
||||
}
|
||||
|
||||
if (this.options.divId) {
|
||||
div = L.DomUtil.get(this.options.divId);
|
||||
L.DomUtil.removeClass(div, 'hidden');
|
||||
this._content.appendChild(div);
|
||||
}
|
||||
|
||||
var stop = L.DomEvent.stopPropagation;
|
||||
L.DomEvent
|
||||
.on(container, 'click', stop)
|
||||
.on(container, 'mousedown', stop)
|
||||
.on(container, 'dblclick', stop);
|
||||
// disabled because links not working, remove?
|
||||
//L.DomEvent.on(container, 'click', L.DomEvent.preventDefault);
|
||||
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
20
js/control/Download.js
Normal file
20
js/control/Download.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
BR.Download = BR.Control.extend({
|
||||
options: {
|
||||
heading: 'Download'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = BR.Control.prototype.onAdd.call(this, map);
|
||||
return container;
|
||||
},
|
||||
|
||||
update: function (urls) {
|
||||
var html = '<div class="label"> </div><div class="value">';
|
||||
if (urls.gpx) {
|
||||
html += '<a href="' + urls.gpx + '" download="brouter.gpx" target="_blank">GPX</a> · ';
|
||||
html += '<a href="' + urls.kml + '" download="brouter.kml" target="_blank">KML</a>';
|
||||
}
|
||||
html += '</div>'
|
||||
this._content.innerHTML = html;
|
||||
}
|
||||
});
|
||||
11
js/control/Profile.js
Normal file
11
js/control/Profile.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
BR.Profile = BR.Control.extend({
|
||||
options: {
|
||||
heading: ''
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = BR.Control.prototype.onAdd.call(this, map);
|
||||
container.innerHTML = " ";
|
||||
return container;
|
||||
}
|
||||
});
|
||||
28
js/control/RoutingOptions.js
Normal file
28
js/control/RoutingOptions.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
BR.RoutingOptions = BR.Control.extend({
|
||||
options: {
|
||||
heading: 'Options',
|
||||
divId: 'route_options'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
L.DomUtil.get('profile').onchange = this._getChangeHandler();
|
||||
L.DomUtil.get('alternative').onchange = this._getChangeHandler();
|
||||
|
||||
return BR.Control.prototype.onAdd.call(this, map);
|
||||
},
|
||||
|
||||
getOptions: function() {
|
||||
return {
|
||||
profile: L.DomUtil.get('profile').value,
|
||||
alternative: L.DomUtil.get('alternative').value
|
||||
};
|
||||
},
|
||||
|
||||
_getChangeHandler: function() {
|
||||
return L.bind(function(evt) {
|
||||
this.fire('update', {options: this.getOptions()});
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
|
||||
BR.RoutingOptions.include(L.Mixin.Events);
|
||||
49
js/control/TrackStats.js
Normal file
49
js/control/TrackStats.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
BR.TrackStats = BR.Control.extend({
|
||||
options: {
|
||||
heading: 'Route'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = BR.Control.prototype.onAdd.call(this, map);
|
||||
this.update();
|
||||
return container;
|
||||
},
|
||||
|
||||
update: function (polyline) {
|
||||
var stats = this.calcStats(polyline),
|
||||
html = '';
|
||||
|
||||
html += '<table id="stats">';
|
||||
html += '<tr><td>Length: </td><td>' + L.Util.formatNum(stats.distance/1000,1) + '</td><td>km</td></tr>';
|
||||
html += '<tr><td>Ascent: </td><td>' + Math.round(stats.elevationGain) + '</td><td>m</td></tr>';
|
||||
html += '<tr><td>Descent: </td><td>' + Math.round(stats.elevationLoss) + '</td><td>m</td></tr>';
|
||||
html += '</table>';
|
||||
|
||||
this._content.innerHTML = html;
|
||||
},
|
||||
|
||||
calcStats: function(polyline) {
|
||||
var stats = {
|
||||
distance: 0,
|
||||
elevationGain: 0,
|
||||
elevationLoss: 0
|
||||
};
|
||||
|
||||
var latLngs = polyline ? polyline.getLatLngs() : [];
|
||||
for (var i = 0, current, next, eleDiff; i < latLngs.length - 1; i++) {
|
||||
current = latLngs[i];
|
||||
next = latLngs[i + 1];
|
||||
stats.distance += current.distanceTo(next);
|
||||
|
||||
// from Leaflet.gpx plugin (writes to LatLng.meta.ele, LatLng now supports ele)
|
||||
eleDiff = (next.ele || next.meta.ele) - (current.ele || current.meta.ele);
|
||||
if (eleDiff > 0) {
|
||||
stats.elevationGain += eleDiff;
|
||||
} else {
|
||||
stats.elevationLoss += Math.abs(eleDiff);
|
||||
}
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
});
|
||||
124
js/index.js
Normal file
124
js/index.js
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
BRouter web - web client for BRouter bike routing engine
|
||||
|
||||
Licensed under the MIT license.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
function initMap() {
|
||||
var odblAttribution = 'data © <a target="_blank" href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors '
|
||||
+ '(<a target="_blank" href="http://opendatacommons.org/licenses/odbl/">ODbL</a>)';
|
||||
|
||||
var landscape = L.tileLayer('http://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: 'tiles © <a target="_blank" href="http://www.thunderforest.com">Thunderforest</a> '
|
||||
+ '(<a target="_blank" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA 2.0</a>)' + odblAttribution
|
||||
});
|
||||
|
||||
var osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: 'tiles © <a target="_blank" href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
});
|
||||
|
||||
var map = new L.Map('map', {
|
||||
layers: [osm],
|
||||
center: new L.LatLng(50.99, 9.86),
|
||||
zoom: 6
|
||||
});
|
||||
map.attributionControl.addAttribution(
|
||||
'<a href="http://dr-brenschede.de/brouter/" target="_blank">BRouter</a> © Arndt Brenschede, '
|
||||
+ 'routing + map data © <a target="_blank" href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors '
|
||||
+ '(<a target="_blank" href="http://opendatacommons.org/licenses/odbl/">ODbL</a>)');
|
||||
|
||||
L.control.layers({
|
||||
'OpenStreetMap': osm,
|
||||
'Landscape (Thunderforest)': landscape
|
||||
}, {
|
||||
/*
|
||||
'Hiking (Waymarked Trails)': hiking
|
||||
*/
|
||||
}).addTo(map);
|
||||
|
||||
map.addControl(new L.Control.Permalink({text: 'Permalink', position: 'bottomright'})); //, layers: layersControl
|
||||
map.addControl(new BR.Search());
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
function initApp(map) {
|
||||
var router,
|
||||
routing,
|
||||
routesLayer,
|
||||
routingOptions,
|
||||
nogos,
|
||||
stats,
|
||||
elevation,
|
||||
download,
|
||||
profile,
|
||||
leftPaneId = 'leftpane';
|
||||
|
||||
// left sidebar as additional control position
|
||||
map._controlCorners[leftPaneId] = L.DomUtil.create('div', 'leaflet-' + leftPaneId, map._controlContainer);
|
||||
|
||||
router = L.bRouter(); //brouterCgi dummyRouter
|
||||
|
||||
function updateRoute(evt) {
|
||||
router.setOptions(evt.options);
|
||||
routing.routeAllSegments(onUpdate);
|
||||
}
|
||||
|
||||
routingOptions = new BR.RoutingOptions();
|
||||
routingOptions.on('update', updateRoute);
|
||||
|
||||
nogos = new BR.NogoAreas();
|
||||
nogos.on('update', updateRoute);
|
||||
|
||||
// initial option settings
|
||||
router.setOptions(nogos.getOptions());
|
||||
router.setOptions(routingOptions.getOptions());
|
||||
|
||||
stats = new BR.TrackStats();
|
||||
download = new BR.Download();
|
||||
elevation = new BR.Elevation();
|
||||
profile = new BR.Profile();
|
||||
|
||||
routing = new BR.Routing({routing: {
|
||||
router: L.bind(router.getRouteSegment, router)
|
||||
}});
|
||||
routing.on('routing:routeWaypointEnd', onUpdate);
|
||||
|
||||
function onUpdate() {
|
||||
var track = routing.toPolyline(),
|
||||
latLngs = routing.getWaypoints(),
|
||||
urls = {};
|
||||
|
||||
elevation.update(track);
|
||||
stats.update(track);
|
||||
|
||||
if (latLngs.length > 1) {
|
||||
urls.gpx = router.getUrl(latLngs, 'gpx');
|
||||
urls.kml = router.getUrl(latLngs, 'kml');
|
||||
}
|
||||
|
||||
download.update(urls);
|
||||
};
|
||||
|
||||
map.addControl(new BR.Control({
|
||||
heading: '',
|
||||
divId: 'header'
|
||||
}));
|
||||
routingOptions.addTo(map);
|
||||
stats.addTo(map);
|
||||
download.addTo(map);
|
||||
elevation.addTo(map);
|
||||
profile.addTo(map);
|
||||
|
||||
nogos.addTo(map);
|
||||
routing.addTo(map);
|
||||
}
|
||||
|
||||
map = initMap();
|
||||
initApp(map);
|
||||
|
||||
})();
|
||||
35
js/plugin/Elevation.js
Normal file
35
js/plugin/Elevation.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
BR.Elevation = L.Control.Elevation.extend({
|
||||
options: {
|
||||
position: "leftpane",
|
||||
width: 385,
|
||||
margins: {
|
||||
top: 20,
|
||||
right: 20,
|
||||
bottom: 30,
|
||||
left: 50
|
||||
},
|
||||
theme: "steelblue-theme" //purple
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this._data = [];
|
||||
this._dist = 0;
|
||||
this._maxElevation = 0;
|
||||
|
||||
// workaround for 'Error: Problem parsing d=""' in Webkit when empty data
|
||||
// https://groups.google.com/d/msg/d3-js/7rFxpXKXFhI/HzIO_NPeDuMJ
|
||||
//this._areapath.datum(this._data).attr("d", this._area);
|
||||
this._areapath.attr("d", "M0 0");
|
||||
|
||||
this._x.domain([0,1]);
|
||||
this._y.domain([0,1]);
|
||||
this._updateAxis();
|
||||
},
|
||||
|
||||
update: function(track) {
|
||||
this.clear();
|
||||
if (track && track.getLatLngs().length > 0) {
|
||||
this.addData(track);
|
||||
}
|
||||
}
|
||||
});
|
||||
66
js/plugin/NogoAreas.js
Normal file
66
js/plugin/NogoAreas.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
L.drawLocal.draw.toolbar.buttons.circle = 'Draw no-go area (circle)';
|
||||
L.drawLocal.edit.toolbar.buttons.edit = 'Edit no-go areas';
|
||||
L.drawLocal.edit.toolbar.buttons.remove = 'Delete no-go areas';
|
||||
|
||||
BR.NogoAreas = L.Control.Draw.extend({
|
||||
initialize: function () {
|
||||
this.drawnItems = new L.FeatureGroup();
|
||||
|
||||
L.Control.Draw.prototype.initialize.call(this, {
|
||||
draw: {
|
||||
position: 'topleft',
|
||||
polyline: false,
|
||||
polygon: false,
|
||||
circle: true,
|
||||
rectangle: false,
|
||||
marker: false
|
||||
},
|
||||
edit: {
|
||||
featureGroup: this.drawnItems,
|
||||
//edit: false,
|
||||
edit: {
|
||||
selectedPathOptions: {
|
||||
//opacity: 0.8
|
||||
}
|
||||
},
|
||||
remove: true
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
map.addLayer(this.drawnItems);
|
||||
|
||||
map.on('draw:created', function (e) {
|
||||
var layer = e.layer;
|
||||
this.drawnItems.addLayer(layer);
|
||||
this._fireUpdate();
|
||||
}, this);
|
||||
|
||||
map.on('draw:editstart', function (e) {
|
||||
this.drawnItems.eachLayer(function (layer) {
|
||||
layer.on('edit', function(e) {
|
||||
this._fireUpdate();
|
||||
}, this);
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
map.on('draw:deleted', function (e) {
|
||||
this._fireUpdate();
|
||||
}, this);
|
||||
|
||||
return L.Control.Draw.prototype.onAdd.call(this, map);
|
||||
},
|
||||
|
||||
getOptions: function() {
|
||||
return {
|
||||
nogos: this.drawnItems.getLayers()
|
||||
};
|
||||
},
|
||||
|
||||
_fireUpdate: function () {
|
||||
this.fire('update', {options: this.getOptions()});
|
||||
}
|
||||
});
|
||||
|
||||
BR.NogoAreas.include(L.Mixin.Events);
|
||||
20
js/plugin/Routing.js
Normal file
20
js/plugin/Routing.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
BR.Routing = L.Routing.extend({
|
||||
options: {
|
||||
/* not implemented yet
|
||||
icons: {
|
||||
start: new L.Icon.Default({iconUrl: 'bower_components/leaflet-gpx/pin-icon-start.png'}),
|
||||
end: new L.Icon.Default(),
|
||||
normal: new L.Icon.Default()
|
||||
},*/
|
||||
snapping: null
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.Routing.prototype.onAdd.call(this, map);
|
||||
|
||||
// enable drawing mode
|
||||
this.draw(true);
|
||||
|
||||
return container;
|
||||
}
|
||||
});
|
||||
17
js/plugin/Search.js
Normal file
17
js/plugin/Search.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
BR.Search = L.Control.Search.extend({
|
||||
options: {
|
||||
//url: 'http://nominatim.openstreetmap.org/search?format=json&q={s}',
|
||||
url: 'http://open.mapquestapi.com/nominatim/v1/search.php?format=json&q={s}',
|
||||
jsonpParam: 'json_callback',
|
||||
propertyName: 'display_name',
|
||||
propertyLoc: ['lat','lon'],
|
||||
markerLocation: false,
|
||||
autoType: false,
|
||||
autoCollapse: true,
|
||||
minLength: 2,
|
||||
zoom: 12
|
||||
},
|
||||
|
||||
// patch: interferes with draw plugin (adds all layers twice to map?)
|
||||
_onLayerAddRemove: function() {}
|
||||
});
|
||||
104
js/router/BRouter.js
Normal file
104
js/router/BRouter.js
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
L.BRouter = L.Class.extend({
|
||||
statics: {
|
||||
// http://localhost:17777/brouter?lonlats=1.1,1.2|2.1,2.2|3.1,3.2|4.1,4.2&nogos=-1.1,-1.2,1|-2.1,-2.2,2&profile=shortest&alternativeidx=1&format=kml
|
||||
URL_TEMPLATE: 'http://localhost:17777/brouter?lonlats={lonlats}&nogos={nogos}&profile={profile}&alternativeidx={alternativeidx}&format={format}',
|
||||
PRECISION: 6,
|
||||
NUMBER_SEPARATOR: ',',
|
||||
GROUP_SEPARATOR: '|'
|
||||
},
|
||||
|
||||
options: {
|
||||
format: 'gpx'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
L.setOptions(this, options);
|
||||
},
|
||||
|
||||
setOptions: function(options) {
|
||||
L.setOptions(this, options);
|
||||
},
|
||||
|
||||
getUrl: function(latLngs, format) {
|
||||
var urlParams = {
|
||||
lonlats: this._getLonLatsString(latLngs),
|
||||
nogos: this._getNogosString(this.options.nogos),
|
||||
profile: this.options.profile,
|
||||
alternativeidx: this.options.alternative,
|
||||
format: format || this.options.format
|
||||
};
|
||||
var url = L.Util.template(L.BRouter.URL_TEMPLATE, urlParams);
|
||||
return url;
|
||||
},
|
||||
|
||||
getRoute: function(latLngs, cb) {
|
||||
var url = this.getUrl(latLngs);
|
||||
if (!url) {
|
||||
return cb(new Error('Error getting route URL'));
|
||||
}
|
||||
|
||||
var gpxLayer = new L.GPX(url, {
|
||||
async: true,
|
||||
polyline_options: {
|
||||
opacity: 0.6
|
||||
},
|
||||
marker_options: {
|
||||
startIconUrl: null,
|
||||
endIconUrl: null
|
||||
}
|
||||
}).on('loaded', function(e) {
|
||||
// leaflet.spin
|
||||
gpxLayer.fire('data:loaded');
|
||||
var gpx = e.target;
|
||||
|
||||
return cb(null, gpx.getLayers()[0]);
|
||||
})/* TODO no error handling in leaflet-gpx
|
||||
.on('error', function(e){
|
||||
console.error('error');
|
||||
gpxLayer.fire('data:loaded');
|
||||
return cb(new Error('Routing failed'));
|
||||
})*/;
|
||||
},
|
||||
|
||||
getRouteSegment: function(l1, l2, cb) {
|
||||
return this.getRoute([l1, l2], cb);
|
||||
},
|
||||
|
||||
_getLonLatsString: function(latLngs) {
|
||||
var s = '';
|
||||
for (var i = 0; i < latLngs.length; i++) {
|
||||
s += this._formatLatLng(latLngs[i]);
|
||||
if (i < (latLngs.length - 1)) {
|
||||
s += L.BRouter.GROUP_SEPARATOR;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
},
|
||||
|
||||
_getNogosString: function(nogos) {
|
||||
var s = '';
|
||||
for (var i = 0, circle; i < nogos.length; i++) {
|
||||
circle = nogos[i];
|
||||
s += this._formatLatLng(circle.getLatLng());
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
s += Math.round(circle.getRadius());
|
||||
if (i < (nogos.length - 1)) {
|
||||
s += L.BRouter.GROUP_SEPARATOR;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
},
|
||||
|
||||
// formats L.LatLng object as lng,lat string
|
||||
_formatLatLng: function(latLng) {
|
||||
var s = '';
|
||||
s += L.Util.formatNum(latLng.lng, L.BRouter.PRECISION);
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
s += L.Util.formatNum(latLng.lat, L.BRouter.PRECISION);
|
||||
return s;
|
||||
}
|
||||
});
|
||||
|
||||
L.bRouter = function (options) {
|
||||
return new L.BRouter(options);
|
||||
};
|
||||
29
js/router/brouterCgi.js
Normal file
29
js/router/brouterCgi.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// BRouter online demo interface
|
||||
// TODO remove or adopt to new structure (only supports two waypoints!)
|
||||
var brouterCgi = (function() {
|
||||
// http://h2096617.stratoserver.net/cgi-bin/brouter.sh?coords=13.404681_52.520185_13.340278_52.512356_trekking_0
|
||||
//var URL_TEMPLATE = '/cgi-bin/proxy.cgi?url=' + 'http://h2096617.stratoserver.net/cgi-bin/brouter.sh?coords={fromLng}_{fromLat}_{toLng}_{toLat}_{profile}_{alt}';
|
||||
var URL_TEMPLATE = '/proxy.php?url=' + 'cgi-bin/brouter.sh?coords={fromLng}_{fromLat}_{toLng}_{toLat}_{profile}_{alt}';
|
||||
var PRECISION = 6;
|
||||
|
||||
function getUrl(polyline) {
|
||||
var latLngs = polyline.getLatLngs();
|
||||
var urlParams = {
|
||||
fromLat: L.Util.formatNum(latLngs[0].lat, PRECISION),
|
||||
fromLng: L.Util.formatNum(latLngs[0].lng, PRECISION),
|
||||
toLat: L.Util.formatNum(latLngs[1].lat, PRECISION),
|
||||
toLng: L.Util.formatNum(latLngs[1].lng, PRECISION),
|
||||
profile: 'trekking',
|
||||
alt: '0'
|
||||
};
|
||||
var url = L.Util.template(URL_TEMPLATE, urlParams);
|
||||
//console.log(url);
|
||||
//return 'test/test.gpx';
|
||||
return url;
|
||||
}
|
||||
|
||||
return {
|
||||
getUrl: getUrl
|
||||
}
|
||||
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue