update Leaflet.Elevation
This commit is contained in:
parent
53587c865b
commit
cec17a1c26
14 changed files with 1360 additions and 929 deletions
|
|
@ -1 +0,0 @@
|
||||||
.lime-theme .leaflet-control.elevation .background{background-color:rgba(156,194,34,.2);-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px}.lime-theme .leaflet-control.elevation .axis path,.lime-theme .leaflet-control.elevation .axis line{fill:none;stroke:#566b13;stroke-width:2}.lime-theme .leaflet-control.elevation .area{fill:#9cc222}.lime-theme .leaflet-control.elevation .mouse-focus-line{pointer-events:none;stroke-width:1;stroke:#101404}.lime-theme .leaflet-control.elevation .elevation-toggle{cursor:pointer;box-shadow:0 1px 7px rgba(0,0,0,.4);-webkit-border-radius:5px;border-radius:5px;width:36px;height:36px;background:url(images/elevation.png) no-repeat center center #f8f8f9}.lime-theme .leaflet-control.elevation-collapsed .background{display:none}.lime-theme .leaflet-control.elevation-collapsed .elevation-toggle{display:block}.lime-theme .leaflet-overlay-pane .height-focus{stroke:#9cc222;fill:#9cc222}.lime-theme .leaflet-overlay-pane .height-focus.line{pointer-events:none;stroke-width:2}.steelblue-theme .leaflet-control.elevation .background{background-color:rgba(70,130,180,.2);-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px}.steelblue-theme .leaflet-control.elevation .axis path,.steelblue-theme .leaflet-control.elevation .axis line{fill:none;stroke:#0d1821;stroke-width:2}.steelblue-theme .leaflet-control.elevation .area{fill:#4682b4}.steelblue-theme .leaflet-control.elevation .mouse-focus-line{pointer-events:none;stroke-width:1;stroke:#0d1821}.steelblue-theme .leaflet-control.elevation .elevation-toggle{cursor:pointer;box-shadow:0 1px 7px rgba(0,0,0,.4);-webkit-border-radius:5px;border-radius:5px;width:36px;height:36px;background:url(images/elevation.png) no-repeat center center #f8f8f9}.steelblue-theme .leaflet-control.elevation-collapsed .background{display:none}.steelblue-theme .leaflet-control.elevation-collapsed .elevation-toggle{display:block}.steelblue-theme .leaflet-overlay-pane .height-focus{stroke:#4682b4;fill:#4682b4}.steelblue-theme .leaflet-overlay-pane .height-focus.line{pointer-events:none;stroke-width:2}.purple-theme .leaflet-control.elevation .background{background-color:rgba(115,44,123,.2);-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px}.purple-theme .leaflet-control.elevation .axis path,.purple-theme .leaflet-control.elevation .axis line{fill:none;stroke:#2d1130;stroke-width:2}.purple-theme .leaflet-control.elevation .area{fill:#732c7b}.purple-theme .leaflet-control.elevation .mouse-focus-line{pointer-events:none;stroke-width:1;stroke:#000}.purple-theme .leaflet-control.elevation .elevation-toggle{cursor:pointer;box-shadow:0 1px 7px rgba(0,0,0,.4);-webkit-border-radius:5px;border-radius:5px;width:36px;height:36px;background:url(images/elevation.png) no-repeat center center #f8f8f9}.purple-theme .leaflet-control.elevation-collapsed .background{display:none}.purple-theme .leaflet-control.elevation-collapsed .elevation-toggle{display:block}.purple-theme .leaflet-overlay-pane .height-focus{stroke:#732c7b;fill:#732c7b}.purple-theme .leaflet-overlay-pane .height-focus.line{pointer-events:none;stroke-width:2}
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,449 +0,0 @@
|
||||||
L.Control.Elevation = L.Control.extend({
|
|
||||||
options: {
|
|
||||||
position: "topright",
|
|
||||||
theme: "lime-theme",
|
|
||||||
width: 600,
|
|
||||||
height: 175,
|
|
||||||
margins: {
|
|
||||||
top: 10,
|
|
||||||
right: 20,
|
|
||||||
bottom: 30,
|
|
||||||
left: 50
|
|
||||||
},
|
|
||||||
useHeightIndicator: true,
|
|
||||||
interpolation: "linear",
|
|
||||||
hoverNumber: {
|
|
||||||
decimalsX: 3,
|
|
||||||
decimalsY: 0,
|
|
||||||
formatter: undefined
|
|
||||||
},
|
|
||||||
xTicks: undefined,
|
|
||||||
yTicks: undefined,
|
|
||||||
collapsed: false
|
|
||||||
},
|
|
||||||
|
|
||||||
onRemove: function(map) {
|
|
||||||
this._container = null;
|
|
||||||
this._data = null;
|
|
||||||
this._dist = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
onAdd: function(map) {
|
|
||||||
this._map = map;
|
|
||||||
|
|
||||||
var opts = this.options;
|
|
||||||
var margin = opts.margins;
|
|
||||||
opts.width = opts.width - margin.left - margin.right;
|
|
||||||
opts.height = opts.height - margin.top - margin.bottom;
|
|
||||||
opts.xTicks = opts.xTicks || Math.round(opts.width / 75);
|
|
||||||
opts.yTicks = opts.yTicks || Math.round(opts.height / 30);
|
|
||||||
opts.hoverNumber.formatter = opts.hoverNumber.formatter || this._formatter;
|
|
||||||
|
|
||||||
//append theme name on body
|
|
||||||
d3.select("body").classed(opts.theme, true);
|
|
||||||
|
|
||||||
var x = this._x = d3.scale.linear()
|
|
||||||
.range([0, opts.width]);
|
|
||||||
|
|
||||||
var y = this._y = d3.scale.linear()
|
|
||||||
.range([opts.height, 0]);
|
|
||||||
|
|
||||||
var area = this._area = d3.svg.area()
|
|
||||||
.interpolate(opts.interpolation)
|
|
||||||
.x(function(d) {
|
|
||||||
return x(d.dist);
|
|
||||||
})
|
|
||||||
.y0(opts.height)
|
|
||||||
.y1(function(d) {
|
|
||||||
return y(d.altitude);
|
|
||||||
});
|
|
||||||
|
|
||||||
var container = this._container = L.DomUtil.create("div", "elevation");
|
|
||||||
|
|
||||||
this._initToggle();
|
|
||||||
|
|
||||||
var complWidth = opts.width + margin.left + margin.right;
|
|
||||||
var cont = d3.select(container);
|
|
||||||
cont.attr("width", complWidth);
|
|
||||||
var svg = cont.append("svg");
|
|
||||||
svg.attr("width", complWidth)
|
|
||||||
.attr("class", "background")
|
|
||||||
.attr("height", opts.height + margin.top + margin.bottom)
|
|
||||||
.append("g")
|
|
||||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
|
||||||
|
|
||||||
var line = d3.svg.line();
|
|
||||||
line = line
|
|
||||||
.x(function(d) {
|
|
||||||
return d3.mouse(svg.select("g"))[0];
|
|
||||||
})
|
|
||||||
.y(function(d) {
|
|
||||||
return opts.height;
|
|
||||||
});
|
|
||||||
|
|
||||||
var g = d3.select(this._container).select("svg").select("g");
|
|
||||||
|
|
||||||
this._areapath = g.append("path")
|
|
||||||
.attr("class", "area");
|
|
||||||
|
|
||||||
var background = this._background = g.append("rect")
|
|
||||||
.attr("width", opts.width)
|
|
||||||
.attr("height", opts.height)
|
|
||||||
.style("fill", "none")
|
|
||||||
.style("stroke", "none")
|
|
||||||
.style("pointer-events", "all");
|
|
||||||
|
|
||||||
background.on("mousemove", this._mousemoveHandler.bind(this));
|
|
||||||
background.on("mouseout", this._mouseoutHandler.bind(this));
|
|
||||||
|
|
||||||
this._xaxisgraphicnode = g.append("g");
|
|
||||||
this._yaxisgraphicnode = g.append("g");
|
|
||||||
this._appendXaxis(this._xaxisgraphicnode);
|
|
||||||
this._appendYaxis(this._yaxisgraphicnode);
|
|
||||||
|
|
||||||
var focusG = this._focusG = g.append("g");
|
|
||||||
this._mousefocus = focusG.append('svg:line')
|
|
||||||
.attr('class', 'mouse-focus-line')
|
|
||||||
.attr('x2', '0')
|
|
||||||
.attr('y2', '0')
|
|
||||||
.attr('x1', '0')
|
|
||||||
.attr('y1', '0');
|
|
||||||
this._focuslabelX = focusG.append("svg:text")
|
|
||||||
.style("pointer-events", "none")
|
|
||||||
.attr("class", "mouse-focus-label-x");
|
|
||||||
this._focuslabelY = focusG.append("svg:text")
|
|
||||||
.style("pointer-events", "none")
|
|
||||||
.attr("class", "mouse-focus-label-y");
|
|
||||||
|
|
||||||
return container;
|
|
||||||
},
|
|
||||||
|
|
||||||
_initToggle: function () {
|
|
||||||
|
|
||||||
/* inspired by L.Control.Layers */
|
|
||||||
|
|
||||||
var container = this._container;
|
|
||||||
|
|
||||||
//Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released
|
|
||||||
container.setAttribute('aria-haspopup', true);
|
|
||||||
|
|
||||||
if (!L.Browser.touch) {
|
|
||||||
L.DomEvent
|
|
||||||
.disableClickPropagation(container);
|
|
||||||
//.disableScrollPropagation(container);
|
|
||||||
} else {
|
|
||||||
L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.options.collapsed)
|
|
||||||
{
|
|
||||||
this._collapse();
|
|
||||||
|
|
||||||
if (!L.Browser.android) {
|
|
||||||
L.DomEvent
|
|
||||||
.on(container, 'mouseover', this._expand, this)
|
|
||||||
.on(container, 'mouseout', this._collapse, this);
|
|
||||||
}
|
|
||||||
var link = this._button = L.DomUtil.create('a', 'elevation-toggle', container);
|
|
||||||
link.href = '#';
|
|
||||||
link.title = 'Elevation';
|
|
||||||
|
|
||||||
if (L.Browser.touch) {
|
|
||||||
L.DomEvent
|
|
||||||
.on(link, 'click', L.DomEvent.stop)
|
|
||||||
.on(link, 'click', this._expand, this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
L.DomEvent.on(link, 'focus', this._expand, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._map.on('click', this._collapse, this);
|
|
||||||
// TODO keyboard accessibility
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_expand: function () {
|
|
||||||
this._container.className = this._container.className.replace(' elevation-collapsed', '');
|
|
||||||
},
|
|
||||||
|
|
||||||
_collapse: function () {
|
|
||||||
L.DomUtil.addClass(this._container, 'elevation-collapsed');
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fromatting funciton using the given decimals and seperator
|
|
||||||
*/
|
|
||||||
_formatter: function(num, dec, sep) {
|
|
||||||
var res;
|
|
||||||
if (dec === 0) {
|
|
||||||
res = Math.round(num) + "";
|
|
||||||
} else {
|
|
||||||
res = L.Util.formatNum(num, dec) + "";
|
|
||||||
}
|
|
||||||
var numbers = res.split(".");
|
|
||||||
if (numbers[1]) {
|
|
||||||
var d = dec - numbers[1].length;
|
|
||||||
for (; d > 0; d--) {
|
|
||||||
numbers[1] += "0";
|
|
||||||
}
|
|
||||||
res = numbers.join(sep || ".");
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
|
|
||||||
_appendYaxis: function(y) {
|
|
||||||
y.attr("class", "y axis")
|
|
||||||
.call(d3.svg.axis()
|
|
||||||
.scale(this._y)
|
|
||||||
.ticks(this.options.yTicks)
|
|
||||||
.orient("left"))
|
|
||||||
.append("text")
|
|
||||||
.attr("x", 15)
|
|
||||||
.style("text-anchor", "end")
|
|
||||||
.text("m");
|
|
||||||
},
|
|
||||||
|
|
||||||
_appendXaxis: function(x) {
|
|
||||||
x.attr("class", "x axis")
|
|
||||||
.attr("transform", "translate(0," + this.options.height + ")")
|
|
||||||
.call(d3.svg.axis()
|
|
||||||
.scale(this._x)
|
|
||||||
.ticks(this.options.xTicks)
|
|
||||||
.orient("bottom"))
|
|
||||||
.append("text")
|
|
||||||
.attr("x", this.options.width + 15)
|
|
||||||
.style("text-anchor", "end")
|
|
||||||
.text("km");
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateAxis: function() {
|
|
||||||
this._xaxisgraphicnode.selectAll("axis").remove();
|
|
||||||
this._yaxisgraphicnode.selectAll("axis").remove();
|
|
||||||
this._appendXaxis(this._xaxisgraphicnode);
|
|
||||||
this._appendYaxis(this._yaxisgraphicnode);
|
|
||||||
},
|
|
||||||
|
|
||||||
_mouseoutHandler: function() {
|
|
||||||
if (this._marker) {
|
|
||||||
this._map.removeLayer(this._marker);
|
|
||||||
this._marker = null;
|
|
||||||
}
|
|
||||||
if (this._mouseHeightFocus) {
|
|
||||||
this._mouseHeightFocus.style("visibility", "hidden");
|
|
||||||
this._mouseHeightFocusLabel.style("visibility", "hidden");
|
|
||||||
}
|
|
||||||
if (this._pointG) {
|
|
||||||
this._pointG.style("visibility", "hidden");
|
|
||||||
}
|
|
||||||
this._focusG.style("visibility", "hidden");
|
|
||||||
},
|
|
||||||
|
|
||||||
_mousemoveHandler: function(d, i, ctx) {
|
|
||||||
if (!this._data || this._data.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var coords = d3.mouse(this._background.node());
|
|
||||||
var opts = this.options;
|
|
||||||
this._focusG.style("visibility", "visible");
|
|
||||||
this._mousefocus.attr('x1', coords[0])
|
|
||||||
.attr('y1', 0)
|
|
||||||
.attr('x2', coords[0])
|
|
||||||
.attr('y2', opts.height)
|
|
||||||
.classed('hidden', false);
|
|
||||||
var bisect = d3.bisector(function(d) {
|
|
||||||
return d.dist;
|
|
||||||
}).left;
|
|
||||||
|
|
||||||
var xinvert = this._x.invert(coords[0]),
|
|
||||||
item = bisect(this._data, xinvert),
|
|
||||||
alt = this._data[item].altitude,
|
|
||||||
dist = this._data[item].dist,
|
|
||||||
ll = this._data[item].latlng,
|
|
||||||
numY = opts.hoverNumber.formatter(alt, opts.hoverNumber.decimalsY),
|
|
||||||
numX = opts.hoverNumber.formatter(dist, opts.hoverNumber.decimalsX);
|
|
||||||
|
|
||||||
this._focuslabelX.attr("x", coords[0])
|
|
||||||
.text(numY + " m");
|
|
||||||
this._focuslabelY.attr("y", opts.height - 5)
|
|
||||||
.attr("x", coords[0])
|
|
||||||
.text(numX + " km");
|
|
||||||
|
|
||||||
var layerpoint = this._map.latLngToLayerPoint(ll);
|
|
||||||
|
|
||||||
//if we use a height indicator we create one with SVG
|
|
||||||
//otherwise we show a marker
|
|
||||||
if (opts.useHeightIndicator) {
|
|
||||||
|
|
||||||
if (!this._mouseHeightFocus) {
|
|
||||||
|
|
||||||
var heightG = d3.select(".leaflet-overlay-pane svg")
|
|
||||||
.append("g");
|
|
||||||
this._mouseHeightFocus = heightG.append('svg:line')
|
|
||||||
.attr('class', 'height-focus line')
|
|
||||||
.attr('x2', '0')
|
|
||||||
.attr('y2', '0')
|
|
||||||
.attr('x1', '0')
|
|
||||||
.attr('y1', '0');
|
|
||||||
|
|
||||||
var pointG = this._pointG = heightG.append("g");
|
|
||||||
pointG.append("svg:circle")
|
|
||||||
.attr("r", 6)
|
|
||||||
.attr("cx", 0)
|
|
||||||
.attr("cy", 0)
|
|
||||||
.attr("class", "height-focus circle-lower");
|
|
||||||
|
|
||||||
this._mouseHeightFocusLabel = heightG.append("svg:text")
|
|
||||||
.attr("class", "height-focus-label")
|
|
||||||
.style("pointer-events", "none");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var normalizedAlt = this.options.height / this._maxElevation * alt;
|
|
||||||
var normalizedY = layerpoint.y - normalizedAlt;
|
|
||||||
this._mouseHeightFocus.attr("x1", layerpoint.x)
|
|
||||||
.attr("x2", layerpoint.x)
|
|
||||||
.attr("y1", layerpoint.y)
|
|
||||||
.attr("y2", normalizedY)
|
|
||||||
.style("visibility", "visible");
|
|
||||||
|
|
||||||
this._pointG.attr("transform", "translate(" + layerpoint.x + "," + layerpoint.y + ")")
|
|
||||||
.style("visibility", "visible");
|
|
||||||
|
|
||||||
this._mouseHeightFocusLabel.attr("x", layerpoint.x)
|
|
||||||
.attr("y", normalizedY)
|
|
||||||
.text(alt + " m")
|
|
||||||
.style("visibility", "visible");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (!this._marker) {
|
|
||||||
|
|
||||||
this._marker = new L.Marker(ll).addTo(this._map);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
this._marker.setLatLng(ll);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parsing of GeoJSON data lines and their elevation in z-coordinate
|
|
||||||
*/
|
|
||||||
_addGeoJSONData: function(coords) {
|
|
||||||
if (coords) {
|
|
||||||
var data = this._data || [];
|
|
||||||
var dist = this._dist || 0;
|
|
||||||
var ele = this._maxElevation || 0;
|
|
||||||
for (var i = 0; i < coords.length; i++) {
|
|
||||||
var s = new L.LatLng(coords[i][1], coords[i][0]);
|
|
||||||
var e = new L.LatLng(coords[i ? i - 1 : 0][1], coords[i ? i - 1 : 0][0]);
|
|
||||||
var newdist = s.distanceTo(e);
|
|
||||||
dist = dist + newdist / 1000;
|
|
||||||
ele = ele < coords[i][2] ? coords[i][2] : ele;
|
|
||||||
data.push({
|
|
||||||
dist: dist,
|
|
||||||
altitude: coords[i][2],
|
|
||||||
x: coords[i][0],
|
|
||||||
y: coords[i][1],
|
|
||||||
latlng: s
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this._dist = dist;
|
|
||||||
this._data = data;
|
|
||||||
this._maxElevation = ele;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parsing function for GPX data as used by https://github.com/mpetazzoni/leaflet-gpx
|
|
||||||
*/
|
|
||||||
_addGPXdata: function(coords) {
|
|
||||||
if (coords) {
|
|
||||||
var data = this._data || [];
|
|
||||||
var dist = this._dist || 0;
|
|
||||||
var ele = this._maxElevation || 0;
|
|
||||||
for (var i = 0; i < coords.length; i++) {
|
|
||||||
var s = coords[i];
|
|
||||||
var e = coords[i ? i - 1 : 0];
|
|
||||||
var newdist = s.distanceTo(e);
|
|
||||||
dist = dist + newdist / 1000;
|
|
||||||
ele = ele < s.meta.ele ? s.meta.ele : ele;
|
|
||||||
data.push({
|
|
||||||
dist: dist,
|
|
||||||
altitude: s.meta.ele,
|
|
||||||
x: s.lng,
|
|
||||||
y: s.lat,
|
|
||||||
latlng: s
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this._dist = dist;
|
|
||||||
this._data = data;
|
|
||||||
this._maxElevation = ele;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_addData: function(d) {
|
|
||||||
var geom = d && d.geometry && d.geometry;
|
|
||||||
var i;
|
|
||||||
|
|
||||||
if (geom) {
|
|
||||||
switch (geom.type) {
|
|
||||||
case 'LineString':
|
|
||||||
this._addGeoJSONData(geom.coordinates);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'MultiLineString':
|
|
||||||
for (i = 0; i < geom.coordinates.length; i++) {
|
|
||||||
this._addGeoJSONData(geom.coordinates[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error('Invalid GeoJSON object.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var feat = d && d.type === "FeatureCollection";
|
|
||||||
if (feat) {
|
|
||||||
for (i = 0; i < d.features.length; i++) {
|
|
||||||
this._addData(d.features[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d && d._latlngs) {
|
|
||||||
this._addGPXdata(d._latlngs);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add data to the diagram either from GPX or GeoJSON and
|
|
||||||
* update the axis domain and data
|
|
||||||
*/
|
|
||||||
addData: function(d) {
|
|
||||||
|
|
||||||
this._addData(d);
|
|
||||||
|
|
||||||
var xdomain = d3.extent(this._data, function(d) {
|
|
||||||
return d.dist;
|
|
||||||
});
|
|
||||||
var ydomain = d3.extent(this._data, function(d) {
|
|
||||||
return d.altitude;
|
|
||||||
});
|
|
||||||
|
|
||||||
this._x.domain(xdomain);
|
|
||||||
this._y.domain(ydomain);
|
|
||||||
this._areapath.datum(this._data)
|
|
||||||
.attr("d", this._area);
|
|
||||||
this._updateAxis();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
L.control.elevation = function(options) {
|
|
||||||
return new L.Control.Elevation(options);
|
|
||||||
};
|
|
||||||
1
bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.css
vendored
Normal file
1
bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.css
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
.lime-theme .leaflet-control.elevation .background{background-color:rgba(156,194,34,.2);-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px}.lime-theme .leaflet-control.elevation .axis line,.lime-theme .leaflet-control.elevation .axis path{fill:none;stroke:#566b13;stroke-width:2}.lime-theme .leaflet-control.elevation .area{fill:#9cc222}.lime-theme .leaflet-control.elevation .mouse-focus-line{pointer-events:none;stroke-width:1;stroke:#101404}.lime-theme .leaflet-control.elevation .elevation-toggle{cursor:pointer;box-shadow:0 1px 7px rgba(0,0,0,.4);-webkit-border-radius:5px;border-radius:5px;width:36px;height:36px;background:url(images/elevation.png) no-repeat center center #f8f8f9}.lime-theme .leaflet-control.elevation-collapsed .background{display:none}.lime-theme .leaflet-control.elevation-collapsed .elevation-toggle{display:block}.lime-theme .leaflet-control.elevation .mouse-drag{fill:rgba(99,126,11,.4)}.lime-theme .leaflet-overlay-pane .height-focus{stroke:#9cc222;fill:#9cc222}.lime-theme .leaflet-overlay-pane .height-focus.line{pointer-events:none;stroke-width:2}.steelblue-theme .leaflet-control.elevation .background{background-color:rgba(70,130,180,.2);-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px}.steelblue-theme .leaflet-control.elevation .axis line,.steelblue-theme .leaflet-control.elevation .axis path{fill:none;stroke:#0d1821;stroke-width:2}.steelblue-theme .leaflet-control.elevation .area{fill:#4682b4}.steelblue-theme .leaflet-control.elevation .mouse-focus-line{pointer-events:none;stroke-width:1;stroke:#0d1821}.steelblue-theme .leaflet-control.elevation .elevation-toggle{cursor:pointer;box-shadow:0 1px 7px rgba(0,0,0,.4);-webkit-border-radius:5px;border-radius:5px;width:36px;height:36px;background:url(images/elevation.png) no-repeat center center #f8f8f9}.steelblue-theme .leaflet-control.elevation-collapsed .background{display:none}.steelblue-theme .leaflet-control.elevation-collapsed .elevation-toggle{display:block}.steelblue-theme .leaflet-control.elevation .mouse-drag{fill:rgba(23,74,117,.4)}.steelblue-theme .leaflet-overlay-pane .height-focus{stroke:#4682b4;fill:#4682b4}.steelblue-theme .leaflet-overlay-pane .height-focus.line{pointer-events:none;stroke-width:2}.purple-theme .leaflet-control.elevation .background{background-color:rgba(115,44,123,.2);-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px}.purple-theme .leaflet-control.elevation .axis line,.purple-theme .leaflet-control.elevation .axis path{fill:none;stroke:#2d1130;stroke-width:2}.purple-theme .leaflet-control.elevation .area{fill:#732c7b}.purple-theme .leaflet-control.elevation .mouse-focus-line{pointer-events:none;stroke-width:1;stroke:#000}.purple-theme .leaflet-control.elevation .elevation-toggle{cursor:pointer;box-shadow:0 1px 7px rgba(0,0,0,.4);-webkit-border-radius:5px;border-radius:5px;width:36px;height:36px;background:url(images/elevation.png) no-repeat center center #f8f8f9}.purple-theme .leaflet-control.elevation-collapsed .background{display:none}.purple-theme .leaflet-control.elevation-collapsed .elevation-toggle{display:block}.purple-theme .leaflet-control.elevation .mouse-drag{fill:rgba(74,14,80,.4)}.purple-theme .leaflet-overlay-pane .height-focus{stroke:#732c7b;fill:#732c7b}.purple-theme .leaflet-overlay-pane .height-focus.line{pointer-events:none;stroke-width:2}
|
||||||
2
bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.min.js
vendored
Normal file
2
bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
675
bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.src.js
vendored
Normal file
675
bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.src.js
vendored
Normal file
|
|
@ -0,0 +1,675 @@
|
||||||
|
L.Control.Elevation = L.Control.extend({
|
||||||
|
options: {
|
||||||
|
position: "topright",
|
||||||
|
theme: "lime-theme",
|
||||||
|
width: 600,
|
||||||
|
height: 175,
|
||||||
|
margins: {
|
||||||
|
top: 10,
|
||||||
|
right: 20,
|
||||||
|
bottom: 30,
|
||||||
|
left: 60
|
||||||
|
},
|
||||||
|
useHeightIndicator: true,
|
||||||
|
interpolation: "linear",
|
||||||
|
hoverNumber: {
|
||||||
|
decimalsX: 3,
|
||||||
|
decimalsY: 0,
|
||||||
|
formatter: undefined
|
||||||
|
},
|
||||||
|
xTicks: undefined,
|
||||||
|
yTicks: undefined,
|
||||||
|
collapsed: false,
|
||||||
|
yAxisMin: undefined,
|
||||||
|
yAxisMax: undefined,
|
||||||
|
forceAxisBounds: false
|
||||||
|
},
|
||||||
|
|
||||||
|
onRemove: function(map) {
|
||||||
|
this._container = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdd: function(map) {
|
||||||
|
this._map = map;
|
||||||
|
|
||||||
|
var opts = this.options;
|
||||||
|
var margin = opts.margins;
|
||||||
|
opts.xTicks = opts.xTicks || Math.round(this._width() / 75);
|
||||||
|
opts.yTicks = opts.yTicks || Math.round(this._height() / 30);
|
||||||
|
opts.hoverNumber.formatter = opts.hoverNumber.formatter || this._formatter;
|
||||||
|
|
||||||
|
//append theme name on body
|
||||||
|
d3.select("body").classed(opts.theme, true);
|
||||||
|
|
||||||
|
var x = this._x = d3.scale.linear()
|
||||||
|
.range([0, this._width()]);
|
||||||
|
|
||||||
|
var y = this._y = d3.scale.linear()
|
||||||
|
.range([this._height(), 0]);
|
||||||
|
|
||||||
|
var area = this._area = d3.svg.area()
|
||||||
|
.interpolate(opts.interpolation)
|
||||||
|
.x(function(d) {
|
||||||
|
return x(d.dist);
|
||||||
|
})
|
||||||
|
.y0(this._height())
|
||||||
|
.y1(function(d) {
|
||||||
|
return y(d.altitude);
|
||||||
|
});
|
||||||
|
|
||||||
|
var container = this._container = L.DomUtil.create("div", "elevation");
|
||||||
|
|
||||||
|
this._initToggle();
|
||||||
|
|
||||||
|
var cont = d3.select(container);
|
||||||
|
cont.attr("width", opts.width);
|
||||||
|
var svg = cont.append("svg");
|
||||||
|
svg.attr("width", opts.width)
|
||||||
|
.attr("class", "background")
|
||||||
|
.attr("height", opts.height)
|
||||||
|
.append("g")
|
||||||
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||||
|
|
||||||
|
var line = d3.svg.line();
|
||||||
|
line = line
|
||||||
|
.x(function(d) {
|
||||||
|
return d3.mouse(svg.select("g"))[0];
|
||||||
|
})
|
||||||
|
.y(function(d) {
|
||||||
|
return this._height();
|
||||||
|
});
|
||||||
|
|
||||||
|
var g = d3.select(this._container).select("svg").select("g");
|
||||||
|
|
||||||
|
this._areapath = g.append("path")
|
||||||
|
.attr("class", "area");
|
||||||
|
|
||||||
|
var background = this._background = g.append("rect")
|
||||||
|
.attr("width", this._width())
|
||||||
|
.attr("height", this._height())
|
||||||
|
.style("fill", "none")
|
||||||
|
.style("stroke", "none")
|
||||||
|
.style("pointer-events", "all");
|
||||||
|
|
||||||
|
if (L.Browser.touch) {
|
||||||
|
|
||||||
|
background.on("touchmove.drag", this._dragHandler.bind(this)).
|
||||||
|
on("touchstart.drag", this._dragStartHandler.bind(this)).
|
||||||
|
on("touchstart.focus", this._mousemoveHandler.bind(this));
|
||||||
|
L.DomEvent.on(this._container, 'touchend', this._dragEndHandler, this);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
background.on("mousemove.focus", this._mousemoveHandler.bind(this)).
|
||||||
|
on("mouseout.focus", this._mouseoutHandler.bind(this)).
|
||||||
|
on("mousedown.drag", this._dragStartHandler.bind(this)).
|
||||||
|
on("mousemove.drag", this._dragHandler.bind(this));
|
||||||
|
L.DomEvent.on(this._container, 'mouseup', this._dragEndHandler, this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this._xaxisgraphicnode = g.append("g");
|
||||||
|
this._yaxisgraphicnode = g.append("g");
|
||||||
|
this._appendXaxis(this._xaxisgraphicnode);
|
||||||
|
this._appendYaxis(this._yaxisgraphicnode);
|
||||||
|
|
||||||
|
var focusG = this._focusG = g.append("g");
|
||||||
|
this._mousefocus = focusG.append('svg:line')
|
||||||
|
.attr('class', 'mouse-focus-line')
|
||||||
|
.attr('x2', '0')
|
||||||
|
.attr('y2', '0')
|
||||||
|
.attr('x1', '0')
|
||||||
|
.attr('y1', '0');
|
||||||
|
this._focuslabelX = focusG.append("svg:text")
|
||||||
|
.style("pointer-events", "none")
|
||||||
|
.attr("class", "mouse-focus-label-x");
|
||||||
|
this._focuslabelY = focusG.append("svg:text")
|
||||||
|
.style("pointer-events", "none")
|
||||||
|
.attr("class", "mouse-focus-label-y");
|
||||||
|
|
||||||
|
if (this._data) {
|
||||||
|
this._applyData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
},
|
||||||
|
|
||||||
|
_dragHandler: function() {
|
||||||
|
|
||||||
|
//we don´t want map events to occur here
|
||||||
|
d3.event.preventDefault();
|
||||||
|
d3.event.stopPropagation();
|
||||||
|
|
||||||
|
this._gotDragged = true;
|
||||||
|
|
||||||
|
this._drawDragRectangle();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draws the currently dragged rectabgle over the chart.
|
||||||
|
*/
|
||||||
|
_drawDragRectangle: function() {
|
||||||
|
|
||||||
|
if (!this._dragStartCoords) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dragEndCoords = this._dragCurrentCoords = d3.mouse(this._background.node());
|
||||||
|
|
||||||
|
var x1 = Math.min(this._dragStartCoords[0], dragEndCoords[0]),
|
||||||
|
x2 = Math.max(this._dragStartCoords[0], dragEndCoords[0]);
|
||||||
|
|
||||||
|
if (!this._dragRectangle && !this._dragRectangleG) {
|
||||||
|
var g = d3.select(this._container).select("svg").select("g");
|
||||||
|
|
||||||
|
this._dragRectangleG = g.append("g");
|
||||||
|
|
||||||
|
this._dragRectangle = this._dragRectangleG.append("rect")
|
||||||
|
.attr("width", x2 - x1)
|
||||||
|
.attr("height", this._height())
|
||||||
|
.attr("x", x1)
|
||||||
|
.attr('class', 'mouse-drag')
|
||||||
|
.style("pointer-events", "none");
|
||||||
|
} else {
|
||||||
|
this._dragRectangle.attr("width", x2 - x1)
|
||||||
|
.attr("x", x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removes the drag rectangle and zoms back to the total extent of the data.
|
||||||
|
*/
|
||||||
|
_resetDrag: function() {
|
||||||
|
|
||||||
|
if (this._dragRectangleG) {
|
||||||
|
|
||||||
|
this._dragRectangleG.remove();
|
||||||
|
this._dragRectangleG = null;
|
||||||
|
this._dragRectangle = null;
|
||||||
|
|
||||||
|
this._hidePositionMarker();
|
||||||
|
|
||||||
|
this._map.fitBounds(this._fullExtent);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handles end of dragg operations. Zooms the map to the selected items extent.
|
||||||
|
*/
|
||||||
|
_dragEndHandler: function() {
|
||||||
|
|
||||||
|
if (!this._dragStartCoords || !this._gotDragged) {
|
||||||
|
this._dragStartCoords = null;
|
||||||
|
this._gotDragged = false;
|
||||||
|
this._resetDrag();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._hidePositionMarker();
|
||||||
|
|
||||||
|
var item1 = this._findItemForX(this._dragStartCoords[0]),
|
||||||
|
item2 = this._findItemForX(this._dragCurrentCoords[0]);
|
||||||
|
|
||||||
|
this._fitSection(item1, item2);
|
||||||
|
|
||||||
|
this._dragStartCoords = null;
|
||||||
|
this._gotDragged = false;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_dragStartHandler: function() {
|
||||||
|
|
||||||
|
d3.event.preventDefault();
|
||||||
|
d3.event.stopPropagation();
|
||||||
|
|
||||||
|
this._gotDragged = false;
|
||||||
|
|
||||||
|
this._dragStartCoords = d3.mouse(this._background.node());
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds a data entry for a given x-coordinate of the diagram
|
||||||
|
*/
|
||||||
|
_findItemForX: function(x) {
|
||||||
|
var bisect = d3.bisector(function(d) {
|
||||||
|
return d.dist;
|
||||||
|
}).left;
|
||||||
|
var xinvert = this._x.invert(x);
|
||||||
|
return bisect(this._data, xinvert);
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Make the map fit the route section between given indexes. */
|
||||||
|
_fitSection: function(index1, index2) {
|
||||||
|
|
||||||
|
var start = Math.min(index1, index2),
|
||||||
|
end = Math.max(index1, index2);
|
||||||
|
|
||||||
|
var ext = this._calculateFullExtent(this._data.slice(start, end));
|
||||||
|
|
||||||
|
this._map.fitBounds(ext);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
_initToggle: function() {
|
||||||
|
|
||||||
|
/* inspired by L.Control.Layers */
|
||||||
|
|
||||||
|
var container = this._container;
|
||||||
|
|
||||||
|
//Makes this work on IE10 Touch devices by stopping it from firing a mouseout event when the touch is released
|
||||||
|
container.setAttribute('aria-haspopup', true);
|
||||||
|
|
||||||
|
if (!L.Browser.touch) {
|
||||||
|
L.DomEvent
|
||||||
|
.disableClickPropagation(container);
|
||||||
|
//.disableScrollPropagation(container);
|
||||||
|
} else {
|
||||||
|
L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.collapsed) {
|
||||||
|
this._collapse();
|
||||||
|
|
||||||
|
if (!L.Browser.android) {
|
||||||
|
L.DomEvent
|
||||||
|
.on(container, 'mouseover', this._expand, this)
|
||||||
|
.on(container, 'mouseout', this._collapse, this);
|
||||||
|
}
|
||||||
|
var link = this._button = L.DomUtil.create('a', 'elevation-toggle', container);
|
||||||
|
link.href = '#';
|
||||||
|
link.title = 'Elevation';
|
||||||
|
|
||||||
|
if (L.Browser.touch) {
|
||||||
|
L.DomEvent
|
||||||
|
.on(link, 'click', L.DomEvent.stop)
|
||||||
|
.on(link, 'click', this._expand, this);
|
||||||
|
} else {
|
||||||
|
L.DomEvent.on(link, 'focus', this._expand, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._map.on('click', this._collapse, this);
|
||||||
|
// TODO keyboard accessibility
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_expand: function() {
|
||||||
|
this._container.className = this._container.className.replace(' elevation-collapsed', '');
|
||||||
|
},
|
||||||
|
|
||||||
|
_collapse: function() {
|
||||||
|
L.DomUtil.addClass(this._container, 'elevation-collapsed');
|
||||||
|
},
|
||||||
|
|
||||||
|
_width: function() {
|
||||||
|
var opts = this.options;
|
||||||
|
return opts.width - opts.margins.left - opts.margins.right;
|
||||||
|
},
|
||||||
|
|
||||||
|
_height: function() {
|
||||||
|
var opts = this.options;
|
||||||
|
return opts.height - opts.margins.top - opts.margins.bottom;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fromatting funciton using the given decimals and seperator
|
||||||
|
*/
|
||||||
|
_formatter: function(num, dec, sep) {
|
||||||
|
var res;
|
||||||
|
if (dec === 0) {
|
||||||
|
res = Math.round(num) + "";
|
||||||
|
} else {
|
||||||
|
res = L.Util.formatNum(num, dec) + "";
|
||||||
|
}
|
||||||
|
var numbers = res.split(".");
|
||||||
|
if (numbers[1]) {
|
||||||
|
var d = dec - numbers[1].length;
|
||||||
|
for (; d > 0; d--) {
|
||||||
|
numbers[1] += "0";
|
||||||
|
}
|
||||||
|
res = numbers.join(sep || ".");
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendYaxis: function(y) {
|
||||||
|
y.attr("class", "y axis")
|
||||||
|
.call(d3.svg.axis()
|
||||||
|
.scale(this._y)
|
||||||
|
.ticks(this.options.yTicks)
|
||||||
|
.orient("left"))
|
||||||
|
.append("text")
|
||||||
|
.attr("x", -45)
|
||||||
|
.attr("y", 3)
|
||||||
|
.style("text-anchor", "end")
|
||||||
|
.text("m");
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendXaxis: function(x) {
|
||||||
|
x.attr("class", "x axis")
|
||||||
|
.attr("transform", "translate(0," + this._height() + ")")
|
||||||
|
.call(d3.svg.axis()
|
||||||
|
.scale(this._x)
|
||||||
|
.ticks(this.options.xTicks)
|
||||||
|
.orient("bottom"))
|
||||||
|
.append("text")
|
||||||
|
.attr("x", this._width() + 20)
|
||||||
|
.attr("y", 15)
|
||||||
|
.style("text-anchor", "end")
|
||||||
|
.text("km");
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateAxis: function() {
|
||||||
|
this._xaxisgraphicnode.selectAll("g").remove();
|
||||||
|
this._xaxisgraphicnode.selectAll("path").remove();
|
||||||
|
this._xaxisgraphicnode.selectAll("text").remove();
|
||||||
|
this._yaxisgraphicnode.selectAll("g").remove();
|
||||||
|
this._yaxisgraphicnode.selectAll("path").remove();
|
||||||
|
this._yaxisgraphicnode.selectAll("text").remove();
|
||||||
|
this._appendXaxis(this._xaxisgraphicnode);
|
||||||
|
this._appendYaxis(this._yaxisgraphicnode);
|
||||||
|
},
|
||||||
|
|
||||||
|
_mouseoutHandler: function() {
|
||||||
|
|
||||||
|
this._hidePositionMarker();
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hides the position-/heigth indication marker drawn onto the map
|
||||||
|
*/
|
||||||
|
_hidePositionMarker: function() {
|
||||||
|
|
||||||
|
if (this._marker) {
|
||||||
|
this._map.removeLayer(this._marker);
|
||||||
|
this._marker = null;
|
||||||
|
}
|
||||||
|
if (this._mouseHeightFocus) {
|
||||||
|
this._mouseHeightFocus.style("visibility", "hidden");
|
||||||
|
this._mouseHeightFocusLabel.style("visibility", "hidden");
|
||||||
|
}
|
||||||
|
if (this._pointG) {
|
||||||
|
this._pointG.style("visibility", "hidden");
|
||||||
|
}
|
||||||
|
this._focusG.style("visibility", "hidden");
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handles the moueseover the chart and displays distance and altitude level
|
||||||
|
*/
|
||||||
|
_mousemoveHandler: function(d, i, ctx) {
|
||||||
|
if (!this._data || this._data.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var coords = d3.mouse(this._background.node());
|
||||||
|
var opts = this.options;
|
||||||
|
this._focusG.style("visibility", "visible");
|
||||||
|
this._mousefocus.attr('x1', coords[0])
|
||||||
|
.attr('y1', 0)
|
||||||
|
.attr('x2', coords[0])
|
||||||
|
.attr('y2', this._height())
|
||||||
|
.classed('hidden', false);
|
||||||
|
var bisect = d3.bisector(function(d) {
|
||||||
|
return d.dist;
|
||||||
|
}).left;
|
||||||
|
|
||||||
|
var item = this._data[this._findItemForX(coords[0])],
|
||||||
|
alt = item.altitude,
|
||||||
|
dist = item.dist,
|
||||||
|
ll = item.latlng,
|
||||||
|
numY = opts.hoverNumber.formatter(alt, opts.hoverNumber.decimalsY),
|
||||||
|
numX = opts.hoverNumber.formatter(dist, opts.hoverNumber.decimalsX);
|
||||||
|
|
||||||
|
this._focuslabelX.attr("x", coords[0])
|
||||||
|
.text(numY + " m");
|
||||||
|
this._focuslabelY.attr("y", this._height() - 5)
|
||||||
|
.attr("x", coords[0])
|
||||||
|
.text(numX + " km");
|
||||||
|
|
||||||
|
var layerpoint = this._map.latLngToLayerPoint(ll);
|
||||||
|
|
||||||
|
//if we use a height indicator we create one with SVG
|
||||||
|
//otherwise we show a marker
|
||||||
|
if (opts.useHeightIndicator) {
|
||||||
|
|
||||||
|
if (!this._mouseHeightFocus) {
|
||||||
|
|
||||||
|
var heightG = d3.select(".leaflet-overlay-pane svg")
|
||||||
|
.append("g");
|
||||||
|
this._mouseHeightFocus = heightG.append('svg:line')
|
||||||
|
.attr('class', 'height-focus line')
|
||||||
|
.attr('x2', '0')
|
||||||
|
.attr('y2', '0')
|
||||||
|
.attr('x1', '0')
|
||||||
|
.attr('y1', '0');
|
||||||
|
|
||||||
|
var pointG = this._pointG = heightG.append("g");
|
||||||
|
pointG.append("svg:circle")
|
||||||
|
.attr("r", 6)
|
||||||
|
.attr("cx", 0)
|
||||||
|
.attr("cy", 0)
|
||||||
|
.attr("class", "height-focus circle-lower");
|
||||||
|
|
||||||
|
this._mouseHeightFocusLabel = heightG.append("svg:text")
|
||||||
|
.attr("class", "height-focus-label")
|
||||||
|
.style("pointer-events", "none");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var normalizedAlt = this._height() / this._maxElevation * alt;
|
||||||
|
var normalizedY = layerpoint.y - normalizedAlt;
|
||||||
|
this._mouseHeightFocus.attr("x1", layerpoint.x)
|
||||||
|
.attr("x2", layerpoint.x)
|
||||||
|
.attr("y1", layerpoint.y)
|
||||||
|
.attr("y2", normalizedY)
|
||||||
|
.style("visibility", "visible");
|
||||||
|
|
||||||
|
this._pointG.attr("transform", "translate(" + layerpoint.x + "," + layerpoint.y + ")")
|
||||||
|
.style("visibility", "visible");
|
||||||
|
|
||||||
|
this._mouseHeightFocusLabel.attr("x", layerpoint.x)
|
||||||
|
.attr("y", normalizedY)
|
||||||
|
.text(alt + " m")
|
||||||
|
.style("visibility", "visible");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!this._marker) {
|
||||||
|
|
||||||
|
this._marker = new L.Marker(ll).addTo(this._map);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
this._marker.setLatLng(ll);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parsing of GeoJSON data lines and their elevation in z-coordinate
|
||||||
|
*/
|
||||||
|
_addGeoJSONData: function(coords) {
|
||||||
|
if (coords) {
|
||||||
|
var data = this._data || [];
|
||||||
|
var dist = this._dist || 0;
|
||||||
|
var ele = this._maxElevation || 0;
|
||||||
|
for (var i = 0; i < coords.length; i++) {
|
||||||
|
var s = new L.LatLng(coords[i][1], coords[i][0]);
|
||||||
|
var e = new L.LatLng(coords[i ? i - 1 : 0][1], coords[i ? i - 1 : 0][0]);
|
||||||
|
var newdist = s.distanceTo(e);
|
||||||
|
dist = dist + Math.round(newdist / 1000 * 100000) / 100000;
|
||||||
|
ele = ele < coords[i][2] ? coords[i][2] : ele;
|
||||||
|
data.push({
|
||||||
|
dist: dist,
|
||||||
|
altitude: coords[i][2],
|
||||||
|
x: coords[i][0],
|
||||||
|
y: coords[i][1],
|
||||||
|
latlng: s
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._dist = dist;
|
||||||
|
this._data = data;
|
||||||
|
this._maxElevation = ele;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parsing function for GPX data as used by https://github.com/mpetazzoni/leaflet-gpx
|
||||||
|
*/
|
||||||
|
_addGPXdata: function(coords) {
|
||||||
|
if (coords) {
|
||||||
|
var data = this._data || [];
|
||||||
|
var dist = this._dist || 0;
|
||||||
|
var ele = this._maxElevation || 0;
|
||||||
|
for (var i = 0; i < coords.length; i++) {
|
||||||
|
var s = coords[i];
|
||||||
|
var e = coords[i ? i - 1 : 0];
|
||||||
|
var newdist = s.distanceTo(e);
|
||||||
|
dist = dist + Math.round(newdist / 1000 * 100000) / 100000;
|
||||||
|
ele = ele < s.meta.ele ? s.meta.ele : ele;
|
||||||
|
data.push({
|
||||||
|
dist: dist,
|
||||||
|
altitude: s.meta.ele,
|
||||||
|
x: s.lng,
|
||||||
|
y: s.lat,
|
||||||
|
latlng: s
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._dist = dist;
|
||||||
|
this._data = data;
|
||||||
|
this._maxElevation = ele;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_addData: function(d) {
|
||||||
|
var geom = d && d.geometry && d.geometry;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
if (geom) {
|
||||||
|
switch (geom.type) {
|
||||||
|
case 'LineString':
|
||||||
|
this._addGeoJSONData(geom.coordinates);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'MultiLineString':
|
||||||
|
for (i = 0; i < geom.coordinates.length; i++) {
|
||||||
|
this._addGeoJSONData(geom.coordinates[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error('Invalid GeoJSON object.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var feat = d && d.type === "FeatureCollection";
|
||||||
|
if (feat) {
|
||||||
|
for (i = 0; i < d.features.length; i++) {
|
||||||
|
this._addData(d.features[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d && d._latlngs) {
|
||||||
|
this._addGPXdata(d._latlngs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates the full extent of the data array
|
||||||
|
*/
|
||||||
|
_calculateFullExtent: function(data) {
|
||||||
|
|
||||||
|
if (!data || data.length < 1) {
|
||||||
|
throw new Error("no data in parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
var ext = new L.latLngBounds(data[0].latlng, data[0].latlng);
|
||||||
|
|
||||||
|
data.forEach(function(item) {
|
||||||
|
ext.extend(item.latlng);
|
||||||
|
});
|
||||||
|
|
||||||
|
return ext;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add data to the diagram either from GPX or GeoJSON and
|
||||||
|
* update the axis domain and data
|
||||||
|
*/
|
||||||
|
addData: function(d) {
|
||||||
|
this._addData(d);
|
||||||
|
if (this._container) {
|
||||||
|
this._applyData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_applyData: function() {
|
||||||
|
var xdomain = d3.extent(this._data, function(d) {
|
||||||
|
return d.dist;
|
||||||
|
});
|
||||||
|
var ydomain = d3.extent(this._data, function(d) {
|
||||||
|
return d.altitude;
|
||||||
|
});
|
||||||
|
var opts = this.options;
|
||||||
|
|
||||||
|
if (opts.yAxisMin !== undefined && (opts.yAxisMin < ydomain[0] || opts.forceAxisBounds)) {
|
||||||
|
ydomain[0] = opts.yAxisMin;
|
||||||
|
}
|
||||||
|
if (opts.yAxisMax !== undefined && (opts.yAxisMax > ydomain[1] || opts.forceAxisBounds)) {
|
||||||
|
ydomain[1] = opts.yAxisMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._x.domain(xdomain);
|
||||||
|
this._y.domain(ydomain);
|
||||||
|
this._areapath.datum(this._data)
|
||||||
|
.attr("d", this._area);
|
||||||
|
this._updateAxis();
|
||||||
|
|
||||||
|
this._fullExtent = this._calculateFullExtent(this._data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset data
|
||||||
|
*/
|
||||||
|
_clearData: function() {
|
||||||
|
this._data = null;
|
||||||
|
this._dist = null;
|
||||||
|
this._maxElevation = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset data and display
|
||||||
|
*/
|
||||||
|
clear: function() {
|
||||||
|
|
||||||
|
this._clearData();
|
||||||
|
|
||||||
|
if (!this._areapath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
L.control.elevation = function(options) {
|
||||||
|
return new L.Control.Elevation(options);
|
||||||
|
};
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 687 B After Width: | Height: | Size: 683 B |
File diff suppressed because it is too large
Load diff
|
|
@ -46,6 +46,9 @@
|
||||||
.mouse-focus-label-x {
|
.mouse-focus-label-x {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
.mouse-drag{
|
||||||
|
fill:@drag-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaflet-overlay-pane {
|
.leaflet-overlay-pane {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
@theme : lime-theme;
|
@theme : lime-theme;
|
||||||
@base-color : #9CC222;
|
@base-color : #9CC222;
|
||||||
|
@highlight-color : #637E0B;
|
||||||
@background : fade(@base-color,20%);
|
@background : fade(@base-color,20%);
|
||||||
|
@drag-color : fade(@highlight-color,40%);
|
||||||
@axis-color : darken(@base-color,20%);
|
@axis-color : darken(@base-color,20%);
|
||||||
@stroke-color : darken(@base-color,40%);
|
@stroke-color : darken(@base-color,40%);
|
||||||
@stroke-width-mouse-focus : 1;
|
@stroke-width-mouse-focus : 1;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
@theme : purple-theme;
|
@theme : purple-theme;
|
||||||
@base-color : #732C7B;
|
@base-color : #732C7B;
|
||||||
|
@highlight-color : #4A0E50;
|
||||||
@background : fade(@base-color,20%);
|
@background : fade(@base-color,20%);
|
||||||
|
@drag-color : fade(@highlight-color,40%);
|
||||||
@axis-color : darken(@base-color,20%);
|
@axis-color : darken(@base-color,20%);
|
||||||
@stroke-color : darken(@base-color,40%);
|
@stroke-color : darken(@base-color,40%);
|
||||||
@stroke-width-mouse-focus : 1;
|
@stroke-width-mouse-focus : 1;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
@theme : steelblue-theme;
|
@theme : steelblue-theme;
|
||||||
@base-color : steelblue;
|
@base-color : #4682B4;
|
||||||
|
@highlight-color : #174A75;
|
||||||
@background : fade(@base-color,20%);
|
@background : fade(@base-color,20%);
|
||||||
|
@drag-color : fade(@highlight-color,40%);
|
||||||
@axis-color : darken(@base-color,40%);
|
@axis-color : darken(@base-color,40%);
|
||||||
@stroke-color : darken(@base-color,40%);
|
@stroke-color : darken(@base-color,40%);
|
||||||
@stroke-width-mouse-focus : 1;
|
@stroke-width-mouse-focus : 1;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<!--[if lte IE 8]>
|
<!--[if lte IE 8]>
|
||||||
<link rel="stylesheet" href="leaflet.draw.ie.css" />
|
<link rel="stylesheet" href="leaflet.draw.ie.css" />
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
<link rel="stylesheet" href="bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.1.css" />
|
<link rel="stylesheet" href="bower_components/Leaflet.Elevation/dist/Leaflet.Elevation-0.0.2.css" />
|
||||||
<link rel="stylesheet" href="bower_components/leaflet-search/dist/leaflet-search.min.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="css/leaflet-routing.css" />
|
||||||
<link rel="stylesheet" href="bower_components/normalize-css/normalize.css" />
|
<link rel="stylesheet" href="bower_components/normalize-css/normalize.css" />
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ BR.Elevation = L.Control.Elevation.extend({
|
||||||
width: 385,
|
width: 385,
|
||||||
margins: {
|
margins: {
|
||||||
top: 20,
|
top: 20,
|
||||||
right: 20,
|
right: 30,
|
||||||
bottom: 30,
|
bottom: 30,
|
||||||
left: 50
|
left: 60
|
||||||
},
|
},
|
||||||
theme: "steelblue-theme" //purple
|
theme: "steelblue-theme" //purple
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue