<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Outdoor on M1CH's Log</title><link>https://blog.m1ch.eu/outdoor/</link><description>Recent content in Outdoor on M1CH's Log</description><generator>Hugo</generator><language>en-us</language><copyright>Michael Klamminger</copyright><lastBuildDate>Tue, 28 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.m1ch.eu/outdoor/index.xml" rel="self" type="application/rss+xml"/><item><title>Meine ersten 200 km</title><link>https://blog.m1ch.eu/outdoor/20260428-200k/</link><pubDate>Tue, 28 Apr 2026 00:00:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20260428-200k/</guid><description>&lt;p&gt;Ich hab&amp;rsquo;s geschafft. Meine ersten 200 km mit dem Rad.&lt;/p&gt;





&lt;div id="gpxstats-be18726634407cf068ed7216b0858712" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:.4rem 1rem;font-size:.875rem;"&gt;&lt;/div&gt;

&lt;script&gt;
(function () {
 var src = "\/gpx\/2026\/2026-04-28.gpx";
 var color = "#e8500a";
 var elId = "gpxstats-be18726634407cf068ed7216b0858712";

 function haversine(a, b) {
 var R = 6371, dLat = (b.lat - a.lat) * Math.PI / 180, dLon = (b.lon - a.lon) * Math.PI / 180;
 var s = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
 Math.cos(a.lat * Math.PI / 180) * Math.cos(b.lat * Math.PI / 180) *
 Math.sin(dLon / 2) * Math.sin(dLon / 2);
 return R * 2 * Math.atan2(Math.sqrt(s), Math.sqrt(1 - s));
 }

 function fmtElapsed(totalMin) {
 var h = Math.floor(totalMin / 60), m = Math.floor(totalMin % 60);
 return h + "h " + (m &lt; 10 ? "0" : "") + m + "m";
 }

 fetch(src)
 .then(function (r) { return r.text(); })
 .then(function (xml) {
 var doc = new DOMParser().parseFromString(xml, "application/xml");
 var nodes = Array.from(doc.querySelectorAll("trkpt"));
 var startMs = null, dist = 0, hasTime = false;
 var pts = [];

 nodes.forEach(function (pt, i) {
 var lat = parseFloat(pt.getAttribute("lat"));
 var lon = parseFloat(pt.getAttribute("lon"));
 var ele = parseFloat((pt.querySelector("ele") || { textContent: 0 }).textContent);
 var ts = (pt.querySelector("time") || { textContent: "" }).textContent;
 var ms = ts ? new Date(ts).getTime() : null;
 if (i === 0) { startMs = ms; if (ms) hasTime = true; }
 if (i &gt; 0) dist += haversine(pts[i - 1], { lat: lat, lon: lon });
 pts.push({
 lat: lat, lon: lon, ele: ele,
 dist: Math.round(dist * 100) / 100,
 elapsedMin: ms !== null &amp;&amp; startMs !== null ? (ms - startMs) / 60000 : i
 });
 });

 var last = pts[pts.length - 1];
 var distMax = last.dist;
 var timeMax = last.elapsedMin;

 

 var SMOOTH_WINDOW = 7;
 var half = Math.floor(SMOOTH_WINDOW / 2);
 var smoothedEle = pts.map(function (p, i) {
 var lo = Math.max(0, i - half), hi = Math.min(pts.length, i + half + 1);
 var sum = 0;
 for (var j = lo; j &lt; hi; j++) sum += pts[j].ele;
 return sum / (hi - lo);
 });

 

 var MAX_GAP_MIN = 3;
 var MOVING_THRESHOLD = 0.5;
 var speed = pts.map(function (p, i) {
 var lo = Math.max(0, i - half), hi = Math.min(pts.length - 1, i + half);
 var dDist = pts[hi].dist - pts[lo].dist;
 var dMin = pts[hi].elapsedMin - pts[lo].elapsedMin;
 return dMin &gt; 0 ? dDist / dMin * 60 : 0;
 });

 var maxEle = -Infinity, minEle = Infinity, gain = 0, loss = 0, movingMin = 0;

 for (var i = 0; i &lt; pts.length; i++) {
 if (pts[i].ele &gt; maxEle) maxEle = pts[i].ele;
 if (pts[i].ele &lt; minEle) minEle = pts[i].ele;
 if (i &gt; 0) {
 var dEleSmoothed = smoothedEle[i] - smoothedEle[i - 1];
 if (dEleSmoothed &gt; 0) gain += dEleSmoothed;
 else loss += -dEleSmoothed;
 var dMin = pts[i].elapsedMin - pts[i - 1].elapsedMin;
 if (dMin &gt; 0 &amp;&amp; dMin &lt;= MAX_GAP_MIN &amp;&amp; speed[i] &gt; MOVING_THRESHOLD) movingMin += dMin;
 }
 }

 var statsData = [
 { label: "Distance", value: distMax.toFixed(1) + " km" },
 { label: "Total time", value: hasTime ? fmtElapsed(timeMax) : "—" },
 { label: "Moving time", value: hasTime ? fmtElapsed(movingMin) : "—" },
 { label: "Elev. gain", value: "+" + Math.round(gain) + " m" },
 { label: "Elev. loss", value: "−" + Math.round(loss) + " m" },
 { label: "Max elev.", value: Math.round(maxEle) + " m" },
 { label: "Min elev.", value: Math.round(minEle) + " m" }
 ];

 document.getElementById(elId).innerHTML = statsData.map(function (s) {
 return '&lt;div style="padding:.3rem .5rem;border-left:2px solid ' + color + '"&gt;' +
 '&lt;div style="font-size:.7rem;opacity:.55;text-transform:uppercase;letter-spacing:.05em;"&gt;' + s.label + '&lt;/div&gt;' +
 '&lt;div style="font-weight:600;"&gt;' + s.value + '&lt;/div&gt;&lt;/div&gt;';
 }).join("");
 });
})();
&lt;/script&gt;

&lt;p&gt;






&lt;link rel="stylesheet" href="https://blog.m1ch.eu/js/leaflet.css"/&gt;
&lt;div id="gpxmap-be18726634407cf068ed7216b0858712" style="height:480px;width:100%;border-radius:4px;"&gt;&lt;/div&gt;
&lt;a href="https://blog.m1ch.eu/gpx/2026/2026-04-28.gpx" download style="display:inline-block;margin-top:.5rem;font-size:.875rem;"&gt;⬇ Download GPX&lt;/a&gt;

&lt;script&gt;
window.gpxLibs = window.gpxLibs || (function () {
 var loading = {};
 function load(url) {
 if (!loading[url]) {
 loading[url] = new Promise(function (resolve, reject) {
 var s = document.createElement("script");
 s.src = url;
 s.onload = resolve;
 s.onerror = function () { reject(new Error("could not load " + url)); };
 document.head.appendChild(s);
 });
 }
 return loading[url];
 }
 return function (urls) {
 return urls.reduce(function (p, url) {
 return p.then(function () { return load(url); });
 }, Promise.resolve());
 };
})();
&lt;/script&gt;

&lt;script&gt;
gpxLibs(["/js/leaflet.js", "/js/leaflet-gpx.js"]).then(function () {
 var color = "#e8500a";
 var src = "\/gpx\/2026\/2026-04-28.gpx";
 var hash = "be18726634407cf068ed7216b0858712";
 var mapId = "gpxmap-be18726634407cf068ed7216b0858712";

 var pts = null;
 var trackMarker = null; 
 var mapTooltip = null;

 function haversine(a, b) {
 var R = 6371, dLat = (b.lat - a.lat) * Math.PI / 180, dLon = (b.lon - a.lon) * Math.PI / 180;
 var s = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
 Math.cos(a.lat * Math.PI / 180) * Math.cos(b.lat * Math.PI / 180) *
 Math.sin(dLon / 2) * Math.sin(dLon / 2);
 return R * 2 * Math.atan2(Math.sqrt(s), Math.sqrt(1 - s));
 }

 function fmtElapsed(totalMin) {
 var h = Math.floor(totalMin / 60), m = Math.floor(totalMin % 60);
 return h + "h " + (m &lt; 10 ? "0" : "") + m + "m";
 }

 
 var map = L.map(mapId, { scrollWheelZoom: true });
 L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
 maxZoom: 19,
 attribution: '&amp;copy; &lt;a href="https://www.openstreetmap.org/copyright"&gt;OpenStreetMap&lt;/a&gt; contributors'
 }).addTo(map);

 new L.GPX(src, {
 async: true,
 polyline_options: { color: color, weight: 3, opacity: 0.9 },
 markers: { startIcon: null, endIcon: null }
 })
 .on("loaded", function (e) { map.fitBounds(e.target.getBounds(), { padding: [20, 20] }); })
 .addTo(map);

 
 mapTooltip = L.tooltip({ sticky: false, opacity: 0.92 });

 function notify(idx) {
 window.dispatchEvent(new CustomEvent("gpx-hover", { detail: { hash: hash, idx: idx, source: "map" } }));
 }

 map.on("mousemove", function (e) {
 if (!pts) return;
 var cur = e.containerPoint;
 var minSq = Infinity, minIdx = -1;
 for (var i = 0; i &lt; pts.length; i++) {
 var pp = map.latLngToContainerPoint(L.latLng(pts[i].lat, pts[i].lon));
 var sq = (pp.x - cur.x) * (pp.x - cur.x) + (pp.y - cur.y) * (pp.y - cur.y);
 if (sq &lt; minSq) { minSq = sq; minIdx = i; }
 }
 if (Math.sqrt(minSq) &gt; 24) {
 mapTooltip.remove();
 notify(null);
 return;
 }
 var pt = pts[minIdx];
 mapTooltip
 .setLatLng([pt.lat, pt.lon])
 .setContent(
 "&lt;b&gt;" + fmtElapsed(pt.elapsedMin) + "&lt;/b&gt;&lt;br&gt;" +
 pt.dist.toFixed(2) + " km ▸ " + Math.round(pt.ele) + " m"
 )
 .addTo(map);
 notify(minIdx);
 });

 map.on("mouseout", function () {
 mapTooltip.remove();
 notify(null);
 });

 
 window.addEventListener("gpx-hover", function (e) {
 if (e.detail.hash !== hash || e.detail.source === "map" || !pts) return;
 var idx = e.detail.idx;
 if (idx === null) return;
 var pt = pts[idx];
 if (!trackMarker) {
 trackMarker = L.circleMarker([pt.lat, pt.lon], {
 radius: 7, color: "#fff", weight: 2, fillColor: color, fillOpacity: 1
 }).addTo(map);
 } else {
 trackMarker.setLatLng([pt.lat, pt.lon]);
 }
 });

 window.addEventListener("gpx-flyto", function (e) {
 if (e.detail.hash !== hash || !pts) return;
 var pt = pts[e.detail.idx];
 map.flyTo([pt.lat, pt.lon], Math.max(map.getZoom(), 13));
 });

 
 fetch(src)
 .then(function (r) { return r.text(); })
 .then(function (xml) {
 var doc = new DOMParser().parseFromString(xml, "application/xml");
 var nodes = Array.from(doc.querySelectorAll("trkpt"));
 var startMs = null, dist = 0;

 pts = [];
 nodes.forEach(function (pt, i) {
 var lat = parseFloat(pt.getAttribute("lat"));
 var lon = parseFloat(pt.getAttribute("lon"));
 var ele = parseFloat((pt.querySelector("ele") || { textContent: 0 }).textContent);
 var ts = (pt.querySelector("time") || { textContent: "" }).textContent;
 var ms = ts ? new Date(ts).getTime() : null;
 if (i === 0) { startMs = ms; }
 if (i &gt; 0) dist += haversine(pts[i - 1], { lat: lat, lon: lon });
 pts.push({
 lat: lat, lon: lon, ele: ele,
 dist: Math.round(dist * 100) / 100,
 elapsedMin: ms !== null &amp;&amp; startMs !== null ? (ms - startMs) / 60000 : i
 });
 });
 });
}).catch(function (err) { console.error("gpx-map:", err); });
&lt;/script&gt;








&lt;div&gt;
 &lt;div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:.4rem;gap:.5rem;flex-wrap:wrap;"&gt;
 &lt;div style="display:flex;flex-direction:column;gap:.35rem;"&gt;
 &lt;div style="display:flex;gap:.3rem;align-items:center;"&gt;
 &lt;span style="font-size:.7rem;opacity:.55;text-transform:uppercase;letter-spacing:.05em;width:1.2rem;"&gt;X&lt;/span&gt;
 &lt;button id="gpxgraph-be18726634407cf068ed7216b0858712-btn-x-dist" style="font-size:.8rem;padding:.2rem .7rem;border:1px solid currentColor;border-radius:3px;cursor:pointer;"&gt;Distance&lt;/button&gt;
 &lt;button id="gpxgraph-be18726634407cf068ed7216b0858712-btn-x-time" style="font-size:.8rem;padding:.2rem .7rem;border:1px solid currentColor;border-radius:3px;cursor:pointer;"&gt;Time&lt;/button&gt;
 &lt;button id="gpxgraph-be18726634407cf068ed7216b0858712-btn-x-clock" style="font-size:.8rem;padding:.2rem .7rem;border:1px solid currentColor;border-radius:3px;cursor:pointer;"&gt;Time of day&lt;/button&gt;
 &lt;/div&gt;
 &lt;div style="display:flex;gap:.3rem;align-items:center;"&gt;
 &lt;span style="font-size:.7rem;opacity:.55;text-transform:uppercase;letter-spacing:.05em;width:1.2rem;"&gt;Y&lt;/span&gt;
 &lt;button id="gpxgraph-be18726634407cf068ed7216b0858712-btn-y-ele" style="font-size:.8rem;padding:.2rem .7rem;border:1px solid currentColor;border-radius:3px;cursor:pointer;"&gt;Elevation&lt;/button&gt;
 &lt;button id="gpxgraph-be18726634407cf068ed7216b0858712-btn-y-speed" style="font-size:.8rem;padding:.2rem .7rem;border:1px solid currentColor;border-radius:3px;cursor:pointer;"&gt;Speed&lt;/button&gt;
 &lt;button id="gpxgraph-be18726634407cf068ed7216b0858712-btn-y-other" style="font-size:.8rem;padding:.2rem .7rem;border:1px solid currentColor;border-radius:3px;cursor:pointer;"&gt;Time&lt;/button&gt;
 &lt;/div&gt;
 &lt;/div&gt;
 &lt;button id="gpxgraph-be18726634407cf068ed7216b0858712-btn-reset" style="font-size:.8rem;padding:.2rem .7rem;border:1px solid currentColor;border-radius:3px;cursor:pointer;background:transparent;opacity:.6;"&gt;Reset zoom&lt;/button&gt;
 &lt;/div&gt;
 &lt;canvas id="gpxgraph-be18726634407cf068ed7216b0858712-chart" style="cursor:crosshair;"&gt;&lt;/canvas&gt;
&lt;/div&gt;

&lt;script&gt;
window.gpxLibs = window.gpxLibs || (function () {
 var loading = {};
 function load(url) {
 if (!loading[url]) {
 loading[url] = new Promise(function (resolve, reject) {
 var s = document.createElement("script");
 s.src = url;
 s.onload = resolve;
 s.onerror = function () { reject(new Error("could not load " + url)); };
 document.head.appendChild(s);
 });
 }
 return loading[url];
 }
 return function (urls) {
 return urls.reduce(function (p, url) {
 return p.then(function () { return load(url); });
 }, Promise.resolve());
 };
})();
&lt;/script&gt;

&lt;script&gt;
gpxLibs(["/js/chart.js", "/js/chartjs-plugin-zoom.js"]).then(function () {
 var trackColor = "#e8500a";
 var src = "\/gpx\/2026\/2026-04-28.gpx";
 var hash = "be18726634407cf068ed7216b0858712";
 var id = "gpxgraph-be18726634407cf068ed7216b0858712";
 var tz = "Europe\/Vienna";

 var pts = null;
 var speed = null;
 var chart = null;
 var xMode = "dist"; 
 var mapHoverIdx = null; 

 

 var NEUTRAL_ACTIVE = { bg: "#333333", fg: "#ffffff" };

 function paintButton(btn, activeInfo) {
 if (activeInfo) {
 btn.style.background = activeInfo.bg;
 btn.style.color = activeInfo.fg;
 btn.style.opacity = "1";
 } else {
 btn.style.background = "transparent";
 btn.style.color = "";
 btn.style.opacity = "0.5";
 }
 }

 function fmtElapsed(totalMin) {
 var h = Math.floor(totalMin / 60), m = Math.floor(totalMin % 60);
 return h + "h " + (m &lt; 10 ? "0" : "") + m + "m";
 }

 
 function fmtClock(min) {
 var t = ((Math.floor(min) % 1440) + 1440) % 1440;
 var h = Math.floor(t / 60), m = t % 60;
 return (h &lt; 10 ? "0" : "") + h + ":" + (m &lt; 10 ? "0" : "") + m;
 }

 
 function clockMinutes(ms) {
 var parts = {};
 new Intl.DateTimeFormat("en-GB", { timeZone: tz, hour: "2-digit", minute: "2-digit",
 second: "2-digit", hourCycle: "h23" })
 .formatToParts(new Date(ms))
 .forEach(function (p) { parts[p.type] = parseInt(p.value, 10); });
 return parts.hour * 60 + parts.minute + parts.second / 60;
 }

 function haversine(a, b) {
 var R = 6371, dLat = (b.lat - a.lat) * Math.PI / 180, dLon = (b.lon - a.lon) * Math.PI / 180;
 var s = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
 Math.cos(a.lat * Math.PI / 180) * Math.cos(b.lat * Math.PI / 180) *
 Math.sin(dLon / 2) * Math.sin(dLon / 2);
 return R * 2 * Math.atan2(Math.sqrt(s), Math.sqrt(1 - s));
 }

 
 window.addEventListener("gpx-hover", function (e) {
 if (e.detail.hash !== hash || e.detail.source === "graph") return;
 mapHoverIdx = e.detail.idx;
 if (!chart) return;
 if (mapHoverIdx === null) {
 chart.tooltip.setActiveElements([], { x: 0, y: 0 });
 } else {
 var meta = chart.getDatasetMeta(0);
 var point = meta.data[mapHoverIdx];
 if (point) chart.tooltip.setActiveElements([{ datasetIndex: 0, index: mapHoverIdx }], { x: point.x, y: point.y });
 }
 chart.update("none");
 });

 
 fetch(src)
 .then(function (r) { return r.text(); })
 .then(function (xml) {
 var doc = new DOMParser().parseFromString(xml, "application/xml");
 var nodes = Array.from(doc.querySelectorAll("trkpt"));
 var startMs = null, dist = 0;

 pts = [];
 nodes.forEach(function (pt, i) {
 var lat = parseFloat(pt.getAttribute("lat"));
 var lon = parseFloat(pt.getAttribute("lon"));
 var ele = parseFloat((pt.querySelector("ele") || { textContent: 0 }).textContent);
 var ts = (pt.querySelector("time") || { textContent: "" }).textContent;
 var ms = ts ? new Date(ts).getTime() : null;
 if (i === 0) { startMs = ms; }
 if (i &gt; 0) dist += haversine(pts[i - 1], { lat: lat, lon: lon });
 pts.push({
 lat: lat, lon: lon, ele: ele,
 dist: Math.round(dist * 100) / 100,
 elapsedMin: ms !== null &amp;&amp; startMs !== null ? (ms - startMs) / 60000 : i
 });
 });

 

 var SMOOTH_WINDOW = 7;
 var half = Math.floor(SMOOTH_WINDOW / 2);
 speed = pts.map(function (p, i) {
 var lo = Math.max(0, i - half), hi = Math.min(pts.length - 1, i + half);
 var dDist = pts[hi].dist - pts[lo].dist;
 var dMin = pts[hi].elapsedMin - pts[lo].elapsedMin;
 return dMin &gt; 0 ? dDist / dMin * 60 : 0;
 });

 var last = pts[pts.length - 1];
 var distMax = last.dist;
 var timeMax = last.elapsedMin;
 var hasTime = startMs !== null;
 

 var startClock = hasTime ? clockMinutes(startMs) : 0;

 

 function otherMode() { return xMode === "dist" ? "time" : "dist"; }
 function xMin() { return xMode === "clock" ? startClock : 0; }
 function xMax() {
 if (xMode === "dist") return distMax;
 if (xMode === "clock") return startClock + timeMax;
 return timeMax;
 }
 function xVal(p) {
 if (xMode === "dist") return p.dist;
 if (xMode === "clock") return startClock + p.elapsedMin;
 return p.elapsedMin;
 }

 

 var Y_METRICS = {
 ele: {
 label: function () { return "Elevation (m)"; },
 color: trackColor,
 active: { bg: trackColor, fg: "#ffffff" },
 value: function (i) { return Math.round(pts[i].ele); },
 tick: function (v) { return v + " m"; }
 },
 speed: {
 label: function () { return "Speed (km/h)"; },
 color: "#90ee90",
 active: { bg: "#90ee90", fg: "#1a1a1a" },
 value: function (i) { return Math.round(speed[i] * 10) / 10; },
 tick: function (v) { return v + " km/h"; }
 },
 other: {
 label: function () { return otherMode() === "dist" ? "Distance (km)" : "Time"; },
 color: "#89cff0",
 active: { bg: "#89cff0", fg: "#1a1a1a" },
 value: function (i) { return otherMode() === "dist" ? pts[i].dist : pts[i].elapsedMin; },
 tick: function (v) { return otherMode() === "dist" ? parseFloat(v.toFixed(2)) + " km" : fmtElapsed(v); }
 }
 };
 var yOrder = ["ele", "speed", "other"];
 var activeY = { ele: true, speed: false, other: false };

 function activeYKeys() {
 return yOrder.filter(function (k) { return activeY[k]; });
 }

 function xTickCb(v) {
 if (xMode === "dist") return parseFloat(v.toFixed(2)) + " km";
 if (xMode === "clock") return fmtClock(v);
 return fmtElapsed(v);
 }

 
 var crosshairPlugin = {
 id: "mapCrosshair",
 afterDraw: function (ch) {
 if (mapHoverIdx === null) return;
 var meta = ch.getDatasetMeta(0);
 var point = meta.data[mapHoverIdx];
 if (!point) return;
 var ctx = ch.ctx;
 ctx.save();
 ctx.beginPath();
 ctx.moveTo(point.x, ch.chartArea.top);
 ctx.lineTo(point.x, ch.chartArea.bottom);
 ctx.lineWidth = 1.5;
 ctx.strokeStyle = trackColor;
 ctx.setLineDash([4, 4]);
 ctx.stroke();
 ctx.restore();
 }
 };

 function buildDatasetsAndScales() {
 var keys = activeYKeys();
 var scales = {
 x: {
 type: "linear",
 min: xMin(), max: xMax(),
 title: { display: true, text: xMode === "dist" ? "Distance (km)" : xMode === "clock" ? "Time of day" : "Time" },
 ticks: { callback: xTickCb, maxTicksLimit: 12 },
 

 afterBuildTicks: xMode !== "clock" ? undefined : function (scale) {
 var span = scale.max - scale.min, step = 180;
 [15, 30, 60, 120, 180].some(function (st) { step = st; return span / st &lt;= 10; });
 var ticks = [];
 for (var v = Math.ceil(scale.min / step) * step; v &lt;= scale.max; v += step) ticks.push({ value: v });
 scale.ticks = ticks;
 }
 }
 };
 var datasets = keys.map(function (key, i) {
 var m = Y_METRICS[key];
 var scaleId = "y_" + key;
 scales[scaleId] = {
 type: "linear",
 position: i % 2 === 0 ? "left" : "right",
 title: { display: true, text: m.label() },
 ticks: { callback: m.tick },
 grid: { drawOnChartArea: i === 0 }
 };
 return {
 yAxisID: scaleId,
 data: pts.map(function (p, idx) { return { x: xVal(p), y: m.value(idx) }; }),
 borderColor: m.color,
 backgroundColor: m.color + "33",
 fill: keys.length === 1,
 pointRadius: 0,
 tension: 0.2,
 borderWidth: 2
 };
 });
 return { datasets: datasets, scales: scales };
 }

 function buildChart() {
 var built = buildDatasetsAndScales();
 var min = xMin();
 var max = xMax();

 if (chart) chart.destroy();

 chart = new Chart(document.getElementById(id + "-chart"), {
 type: "line",
 plugins: [crosshairPlugin],
 data: { datasets: built.datasets },
 options: {
 responsive: true,
 parsing: false,
 animation: false,

 onClick: function (event, activeElements, ch) {
 var els = activeElements.length
 ? activeElements
 : ch.getElementsAtEventForMode(event.native || event, "index", { intersect: false }, false);
 if (!els.length) return;
 window.dispatchEvent(new CustomEvent("gpx-flyto", { detail: { hash: hash, idx: els[0].index } }));
 },

 onHover: function (event, activeElements) {
 if (!activeElements.length) return;
 window.dispatchEvent(new CustomEvent("gpx-hover", { detail: { hash: hash, idx: activeElements[0].index, source: "graph" } }));
 },

 interaction: { mode: "index", intersect: false },

 plugins: {
 legend: { display: false },
 tooltip: {
 mode: "index",
 intersect: false,
 callbacks: {
 title: function (items) {
 var e = pts[items[0].dataIndex].elapsedMin;
 return fmtElapsed(e) + (hasTime ? " (" + fmtClock(startClock + e) + ")" : "");
 },
 label: function (item) {
 var i = item.dataIndex;
 return [
 "Distance: " + pts[i].dist.toFixed(2) + " km",
 "Elevation: " + Math.round(pts[i].ele) + " m",
 "Speed: " + (Math.round(speed[i] * 10) / 10) + " km/h"
 ];
 }
 }
 },
 zoom: {
 zoom: { wheel: { enabled: true }, mode: "x" },
 pan: { enabled: true, mode: "x" },
 limits: { x: { min: min, max: max, minRange: (max - min) * 0.02 } }
 }
 },

 scales: built.scales
 }
 });
 }

 buildChart();

 
 var btnXDist = document.getElementById(id + "-btn-x-dist");
 var btnXTime = document.getElementById(id + "-btn-x-time");
 var btnXClock = document.getElementById(id + "-btn-x-clock");
 if (!hasTime) btnXClock.style.display = "none";
 var btnYEle = document.getElementById(id + "-btn-y-ele");
 var btnYSpeed = document.getElementById(id + "-btn-y-speed");
 var btnYOther = document.getElementById(id + "-btn-y-other");
 var btnReset = document.getElementById(id + "-btn-reset");
 var yButtons = { ele: btnYEle, speed: btnYSpeed, other: btnYOther };

 function refreshXButtons() {
 paintButton(btnXDist, xMode === "dist" ? NEUTRAL_ACTIVE : null);
 paintButton(btnXTime, xMode === "time" ? NEUTRAL_ACTIVE : null);
 paintButton(btnXClock, xMode === "clock" ? NEUTRAL_ACTIVE : null);
 }

 function refreshYButtons() {
 btnYOther.textContent = otherMode() === "dist" ? "Distance" : "Time";
 yOrder.forEach(function (key) {
 paintButton(yButtons[key], activeY[key] ? Y_METRICS[key].active : null);
 });
 }

 function switchX(newMode) {
 if (newMode === xMode) return;
 xMode = newMode;
 refreshXButtons();
 refreshYButtons(); 
 buildChart();
 }

 function toggleY(key) {
 var willBeActive = !activeY[key];
 if (!willBeActive &amp;&amp; activeYKeys().length === 1) return; 
 activeY[key] = willBeActive;
 refreshYButtons();
 buildChart();
 }

 refreshXButtons();
 refreshYButtons();

 btnXDist.addEventListener("click", function () { switchX("dist"); });
 btnXTime.addEventListener("click", function () { switchX("time"); });
 btnXClock.addEventListener("click", function () { switchX("clock"); });
 btnYEle.addEventListener("click", function () { toggleY("ele"); });
 btnYSpeed.addEventListener("click", function () { toggleY("speed"); });
 btnYOther.addEventListener("click", function () { toggleY("other"); });
 btnReset.addEventListener("click", function () { chart.resetZoom(); });
 });
}).catch(function (err) { console.error("gpx-graph:", err); });
&lt;/script&gt;
&lt;/p&gt;</description></item><item><title>Steiermarkumwanderung - Etappe 10</title><link>https://blog.m1ch.eu/outdoor/20200706-etape10/</link><pubDate>Mon, 06 Jul 2020 00:00:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20200706-etape10/</guid><description>&lt;h3 id="tag-31-2020-07-06---über-den-sarstein"&gt;Tag 31 (2020-07-06) - Über den Sarstein&lt;/h3&gt;

&lt;div class="day-stations"&gt;
&lt;div class="day-stations-title"&gt;Quick Facts&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Stationen:&lt;/strong&gt; Pötschenpass → Sarsteinalm → Hoher Sarstein (1975 m) → Sarsteinhütte → Obertraun&lt;br&gt;
&lt;strong&gt;Höchster Punkt:&lt;/strong&gt; Hoher Sarstein, 1968 m&lt;br&gt;
&lt;strong&gt;Länge:&lt;/strong&gt; 13,4 km&lt;/p&gt;

&lt;/div&gt;

&lt;p&gt;In vier Tagen Pause konnte ich mich gut erholen. Eva hat Verwandte in Oberösterreich, und da hat sie beschlossen, diese zu besuchen und mich am Weg abzusetzen.&lt;/p&gt;
&lt;p&gt;In der Früh hat sie mich dann am Pötschenpass, zwischen Altaussee und Hallstätter See, abgesetzt. Die ersten 1,5 km waren mir noch wohlbekannt, bin ich sie doch erst fünf Tage zuvor gegangen, damals noch in der Hoffnung, dass ich es vor dem Gewitter auf den Sarstein schaffe.&lt;/p&gt;</description></item><item><title>231.336 Schritte - Statistik durchs Tote Gebirge</title><link>https://blog.m1ch.eu/outdoor/20200705-statistik-durchs-tote-gebirge/</link><pubDate>Sun, 05 Jul 2020 13:18:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20200705-statistik-durchs-tote-gebirge/</guid><description>&lt;p&gt;Nachdem ich das Tote Gebirge durchquert hatte, die Wettervorhersage alles andere als gut war und auch mein Körper eine Pause vertragen konnte, bin ich kurzerhand nach Hause gefahren und habe mich ein paar Tage lang entspannt.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.m1ch.eu/images/outdoor/20200705/track-part.webp" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Am Kartenausschnitt oben kann man meinen Weg durchs Tote Gebirge ganz gut erkennen. Leider war es mir nicht immer möglich, genau der Grenze zu folgen. Vor allem den Abschnitt über den Stoderkamm, vom Großen Tragl zum Feuerberg, habe ich diesmal ausgelassen, da noch zu viel Schnee lag und ich alleine unterwegs war. Diese Etappe möchte ich aber auf jeden Fall noch nachholen!&lt;/p&gt;</description></item><item><title>Steiermarkumwanderung - Etappe 9</title><link>https://blog.m1ch.eu/outdoor/20200630-etape9/</link><pubDate>Tue, 30 Jun 2020 00:00:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20200630-etape9/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Nach zwei Tagen Pause geht es weiter: ein einsamer Tag über die Gipfel
rund um den Rinnerkogel zur Ischler Hütte &amp;ndash; und ein Tag, der mit
neugierigen Kühen beginnt und im Gewitter am Sommersbergsee endet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="tag-29-2020-06-30"&gt;Tag 29 (2020-06-30)&lt;/h3&gt;

&lt;div class="day-stations"&gt;
&lt;div class="day-stations-title"&gt;Quick Facts&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Stationen:&lt;/strong&gt; Rinnerhütte → Rinnerkogel (Augstkogel) (2012 m) → Wehrkogel (2008 m) → Großer Wildenkogel (2093 m) → Schönberg (Wildenkogel) (2090 m) → Ischler Hütte&lt;br&gt;
&lt;strong&gt;Höchster Punkt:&lt;/strong&gt; Schönberg (Wildenkogel), 2089 m&lt;br&gt;
&lt;strong&gt;Länge:&lt;/strong&gt; 13,9 km&lt;/p&gt;</description></item><item><title>Steiermarkumwanderung - Etappe 8</title><link>https://blog.m1ch.eu/outdoor/20200624-etape8/</link><pubDate>Wed, 24 Jun 2020 00:00:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20200624-etape8/</guid><description>&lt;blockquote&gt;
&lt;p&gt;Nach fast sieben Jahren geht es weiter: über fünf Zweitausender zur
Hochmölbinghütte, mit einem Umweg über Hinterstoder zum Prielschutzhaus,
über das verschneite Plateau des Toten Gebirges zum Albert Appel-Haus und
zur Rinnerhütte &amp;ndash; und danach zwei Tage Pause.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="tag-25-2020-06-24"&gt;Tag 25 (2020-06-24)&lt;/h3&gt;

&lt;div class="day-stations"&gt;
&lt;div class="day-stations-title"&gt;Quick Facts&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Stationen:&lt;/strong&gt; Pyhrn → Geißfeld (1727 m) → Lärchkogel (1788 m) → Elmscharte → Schrocken (2281 m) → Kaminspitz (2322 m) → Kreuzspitze (2327 m) → Hochmölbing (2336 m) → Mittermölbing (2318 m) → Kleinmölbing (2160 m) → Hochmölbinghütte&lt;br&gt;
&lt;strong&gt;Höchster Punkt:&lt;/strong&gt; Hochmölbing, 2332 m&lt;br&gt;
&lt;strong&gt;Länge:&lt;/strong&gt; 25,3 km&lt;/p&gt;</description></item><item><title>Weiter gehts</title><link>https://blog.m1ch.eu/outdoor/20200623-weiter-gehts/</link><pubDate>Tue, 23 Jun 2020 21:17:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20200623-weiter-gehts/</guid><description>&lt;p&gt;Später als gedacht (zuerst bin ich von der Arbeit nicht weggekommen und jetzt waren doch mehrere Tage Planung notwendig) werde ich jetzt wieder aufbrechen.&lt;/p&gt;
&lt;p&gt;Der Rucksack ist gepackt und morgen werde ich um 5h früh den Zug nach Liezen nehmen und dann weiter mit dem Bus auf den Pyrn. Aber genug von meinen Plänen. Ich will jetzt einmal kurz über das bereits geschaffte schreiben.&lt;/p&gt;
&lt;h3 id="bilanz-nach-24-gehtagen"&gt;Bilanz nach 24 Gehtagen&lt;/h3&gt;
&lt;p&gt;Bis jetzt hatte ich insgesamt &lt;strong&gt;24 Gehtage&lt;/strong&gt; an der steirischen Grenze.&lt;/p&gt;</description></item><item><title>Schladminger Tauern Überschreitung</title><link>https://blog.m1ch.eu/outdoor/20200611-schladminger-tauern/</link><pubDate>Thu, 11 Jun 2020 00:00:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20200611-schladminger-tauern/</guid><description>&lt;h1 id="der-erste-wandertag-seit-langem"&gt;Der erste Wandertag seit langem&lt;/h1&gt;
&lt;p&gt;Nicht die erste Wanderung seit langem. Noch nicht einmal die erste Mehrtageswanderung heuer. Nein, die erste Wanderung, die es wieder in meinen Blog schafft. 😃&lt;/p&gt;
&lt;p&gt;Link zur &lt;a href="https://www.alpenvereinaktiv.com/s/etUHP"&gt;Tour&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="tag-1"&gt;Tag 1&lt;/h1&gt;
&lt;p&gt;Heute sind wir um 6h in Graz weggefahren, um ja den Wanderbus ins Untertal zu erwischen.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.m1ch.eu/images/outdoor/20200611/2020-06-11T081714.webp" alt="Selfie von Eva und mir vor dem rauschenden Bach im Untertal"&gt;&lt;/p&gt;
&lt;p&gt;Gestartet sind wir heut vom Parkplatz Riesachfall, mit dem Ziel Preintalerhütte. Trotz der Bilder von der Hängebrücke im durch die Höll Steig hat sich Eva getraut und nicht die Almstraße genommen. Und es hat sich gelohnt😁&lt;/p&gt;</description></item><item><title>Sieben Jahre nichts passiert?</title><link>https://blog.m1ch.eu/outdoor/20200610-sieben-jahre-nichts-passiert/</link><pubDate>Wed, 10 Jun 2020 00:26:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20200610-sieben-jahre-nichts-passiert/</guid><description>&lt;p&gt;Fast sieben Jahre hat sich hier nichts getan. Das heißt nicht, dass ich untätig war! Ich bin nach meiner letzten Vier-Tages-Etappe nur abgekommen von meinem Vorhaben, die Steiermark zu umrunden. Nicht dass ich es nicht mehr will, aber in meinem Leben haben sich die Prioritäten geändert.&lt;/p&gt;
&lt;p&gt;Der erste fixe Job und ehe man sich versieht, hat man eine Pause von sieben Jahren gemacht. Das letzte Mal hatte ich mir im Jahr 2017 eine Woche Urlaub genommen, um weiterzugehen. Und dann war Regen angesagt. Sonst ist an meinem Vorhaben nichts weitergegangen.&lt;/p&gt;</description></item><item><title>Weg mit Bildern</title><link>https://blog.m1ch.eu/outdoor/20130819-weg-mit-bildern/</link><pubDate>Mon, 19 Aug 2013 21:38:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20130819-weg-mit-bildern/</guid><description>&lt;p&gt;&lt;img src="https://blog.m1ch.eu/images/outdoor/20130819/test.webp" alt="Karte der Steiermark mit dem bisherigen Weg entlang der Landesgrenze und den Fotos an den Orten, an denen sie entstanden sind"&gt;&lt;/p&gt;
&lt;p&gt;Eine kleine Visualisierung meines bisherigen Weges mit allen Fotos, die ich gemacht habe.&lt;/p&gt;</description></item><item><title>Steiermarkumwanderung</title><link>https://blog.m1ch.eu/outdoor/20130717-rucksack-ist-gepackt-gps-ist/</link><pubDate>Wed, 17 Jul 2013 00:00:00 +0000</pubDate><guid>https://blog.m1ch.eu/outdoor/20130717-rucksack-ist-gepackt-gps-ist/</guid><description>&lt;h2 id="der-rucksack-ist-gepackt"&gt;Der Rucksack ist gepackt&lt;/h2&gt;
&lt;p&gt;Rucksack ist gepackt; GPS ist programmiert. Jetzt muss ich nur noch eine Möglichkeit finden, um an den Start zu kommen.&lt;/p&gt;
&lt;p&gt;Starten werde ich an der südlichsten Stelle der Steiermark in Schloßberg und dann werde ich gegen den Uhrzeigersinn gehen. Als Startpunkt habe ich diese Stelle und Richtung gewählt, damit ich den &amp;ldquo;langweiligsten&amp;rdquo; Teil gleich am Anfang hinter mich bringe.&lt;/p&gt;
&lt;h2 id="zum-projekt"&gt;Zum Projekt&lt;/h2&gt;
&lt;p&gt;Der Einfall, die Steiermark zu Fuß zu umrunden, ist mir schon vor vielen Jahren gekommen. Irgendwann habe ich es dann davon zu erzählen begonnen und, um es für mich selbst konkret zu machen, habe ich es, als ein Ende meines Studiums in Sicht war, mit diesem zu verknüpfen begonnen. &amp;ldquo;Wenn ich meinen Abschluss habe, gehe ich einmal zu Fuß um die Steiermark.&amp;rdquo;&lt;/p&gt;</description></item></channel></rss>