ol-elevation-profile 0.6.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/ol-elevation-profile.css +22 -6
- package/dist/ol-elevation-profile.esm.js +411 -59
- package/dist/ol-elevation-profile.esm.min.js +6 -4
- package/dist/ol-elevation-profile.js +411 -59
- package/dist/ol-elevation-profile.min.js +7 -5
- package/package.json +3 -3
- package/src/ol-elevation-profile.css +22 -6
- package/src/ol-elevation-profile.js +411 -59
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/*! ol-elevation-profile | MIT License | https://github.com/lc-4918/ol-elevation-profile */
|
|
2
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("ol/control/Control.js"),require("ol/Overlay.js"),require("ol/Observable.js"),require("ol/proj.js"),require("ol/sphere.js"),require("ol/extent.js"),require("d3")):"function"==typeof define&&define.amd?define(["ol/control/Control.js","ol/Overlay.js","ol/Observable.js","ol/proj.js","ol/sphere.js","ol/extent.js","d3"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).OlElevationProfile=e(t.ol.control.Control,t.ol.Overlay,t.ol.Observable,t.ol.proj,t.ol.sphere,t.ol.extent,t.d3)}(this,function(t,e,s,o,i,n,l){"use strict";function
|
|
2
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("ol/control/Control.js"),require("ol/Overlay.js"),require("ol/Observable.js"),require("ol/proj.js"),require("ol/sphere.js"),require("ol/extent.js"),require("d3")):"function"==typeof define&&define.amd?define(["ol/control/Control.js","ol/Overlay.js","ol/Observable.js","ol/proj.js","ol/sphere.js","ol/extent.js","d3"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).OlElevationProfile=e(t.ol.control.Control,t.ol.Overlay,t.ol.Observable,t.ol.proj,t.ol.sphere,t.ol.extent,t.d3)}(this,function(t,e,s,o,i,n,l){"use strict";function r(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(s){if("default"!==s){var o=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(e,s,o.get?o:{enumerable:!0,get:function(){return t[s]}})}}),e.default=t,Object.freeze(e)}var a=r(l);
|
|
3
3
|
/**
|
|
4
4
|
* Synchronized elevation profile control for OpenLayers, rendered with d3.
|
|
5
5
|
*
|
|
6
|
-
* Reads elevation (Z) directly from 3D line geometries (`[lon, lat, z]`)
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Reads elevation (Z) directly from 3D line geometries (`[lon, lat, z]`). A track without
|
|
7
|
+
* Z is completed from a terrain model - keyless AWS Terrain Tiles by default, which means
|
|
8
|
+
* the control fetches tiles on its own; set `dem: null` to keep it entirely offline.
|
|
9
|
+
* Clicking (or hovering) a track shows its profile; a marker stays synchronized on both
|
|
10
|
+
* the map and the chart.
|
|
9
11
|
*
|
|
10
12
|
* Peer dependencies (provided by the host application, not bundled):
|
|
11
13
|
* - OpenLayers >= 6 (https://openlayers.org/)
|
|
@@ -13,4 +15,4 @@
|
|
|
13
15
|
*
|
|
14
16
|
* @module ol-elevation-profile
|
|
15
17
|
* @license MIT
|
|
16
|
-
*/const h={steelblue:{area:"#4682b4",line:"#3a6d96",axis:"#555",text:"#222",focus:"#e6550d"},lime:{area:"#9ccc2f",line:"#7da521",axis:"#555",text:"#222",focus:"#d62728"},purple:{area:"#9467bd",line:"#76529c",axis:"#555",text:"#222",focus:"#ff9f1c"},slate:{area:"#7c8a99",line:"#4a5560",axis:"#5a6570",text:"#26303a",focus:"#2f81f7"},graphite:{area:"#9a948c",line:"#5c574f",axis:"#5c574f",text:"#2b2823",focus:"#e07a3f"},amber:{area:"#f0a23b",line:"#c4671a",axis:"#7a5a36",text:"#3a2a16",focus:"#1f6fb2"}},p=["top","bottom","left","right","top-left","top-right","bottom-left","bottom-right"],c={immersion:"docked",position:"bottom",width:520,height:180,margins:{unit:"px",top:20,right:24,bottom:30,left:48},units:"meters",dataProjection:null,maxPoints:2e3,smoothing:0,theme:"steelblue",color:null,trackLayer:null,transparency:!1,transparencyLevel:.45,grid:!0,slope:!1,slopeClassSize:2.5,slopeColors:null,slopeSeparators:!0,slopeLegend:!0,maxClasses:8,xTicks:null,yTicks:null,show:"click",collapsable:!0,collapsed:!1,followMap:!0,marker:!0,hideOnMapClick:!0,responsive:!0,mobileBreakpoint:640,zoom:!1,ignoreStops:!0,stopSpeed:.5,tooltipItems:["distance","elevation"],headerItems:["distance","ascent","descent","minmax"],titleProperty:"name",titleLink:null,labels:{distance:"Distance",elevation:"Altitude",slope:"Pente",ascent:"D+",descent:"D-",empty:"Cliquez un tracé",time:"Temps",duration:"Durée",durationUnits:{s:"sec",m:"min",h:"h",d:"j"},zoomStart:"Définir le début (A)",zoomEnd:"Définir la fin (B)",zoomAll:"Tout voir"}};function u(t,e){const s={};return Object.keys(t).forEach(e=>{s[e]=t[e]}),e&&Object.keys(e).forEach(o=>{e[o]&&"object"==typeof e[o]&&!Array.isArray(e[o])&&t[o]&&"object"==typeof t[o]?s[o]=u(t[o],e[o]):s[o]=e[o]}),s}const d=t=>String(t).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[t])),m=t=>"string"==typeof t&&/^(https?:)?\/\/|^mailto:/i.test(t);function _(t,e){const s=t&&t.getProperties?t.getProperties():{};let o=s.coordTimes;null==o&&s.coordinateProperties&&(o=s.coordinateProperties.times||s.coordinateProperties.coordTimes);let i=null;if(Array.isArray(o)&&(i=Array.isArray(o[0])?o.reduce((t,e)=>t.concat(e),[]):o.slice()),!i&&e){const t=[];let s=!1;for(const o of e)for(const e of o){const o=e.length>3?e[3]:null;t.push(o),null!=o&&isFinite(o)&&(s=!0)}i=s?t:null}if(!i)return null;let n=0;const l=i.map(t=>{if(null==t||""===t)return null;const e="number"==typeof t?t>1e12?t:1e3*t:Date.parse(t);return isFinite(e)?(n++,e):null});return n>=2?l:null}function f(t,e,s){let o=t;if("function"==typeof o)try{o=o(e,s)}catch(t){return null}if(Array.isArray(o)&&(o=o[0]),o&&o.getStroke){const t=o.getStroke();if(t)return t.getColor()}return null}const g=(t,e)=>{if("imperial"===e){const e=t/1609.344;return e<.2?`${Math.round(3.28084*t)} ft`:`${e.toFixed(e<10?2:1)} mi`}return t<1e3?`${Math.round(t)} m`:`${(t/1e3).toFixed(t<1e4?2:1)} km`},y=(t,e)=>"imperial"===e?`${Math.round(3.28084*t)} ft`:`${Math.round(t)} m`;const x='<svg viewBox="0 0 24 24"><path d="M5 13h14" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></svg>',b='<svg viewBox="0 0 24 24"><path d="M3 19l5-7 4 4 4-6 5 9z" fill="currentColor" opacity=".85"/></svg>';class M extends t{constructor(t){const e=u(c,t||{});-1===p.indexOf(e.position)&&(e.position="bottom");const s=function(t){const e=document.createElement("div");return e.className=`ol-elevation-profile ol-unselectable ol-control oep-pos-${t.position} oep-theme-${"string"==typeof t.theme?t.theme:"custom"}`+("floating"===t.immersion?" oep-floating":""),e}(e);super({element:s,target:t&&t.target}),this.options=e,this.slopeColors=e.slopeColors||null,this._feature=null,this._fullSamples=null,this._fullStats=null,this._samples=null,this._stats=null,this._marker=null,this._collapsed=!!e.collapsed,this._cropMode=!1,this._zoomA=null,this._zoomB=null,this._armed=null,this._fitRes=null,this._onResize=()=>{this._feature&&!this._collapsed&&this._render()},this._buildDom(s),s.style.display="none"}static featureHasZ(t){const e=t&&t.getGeometry&&t.getGeometry();if(!e)return!1;const s="MultiLineString"===e.getType()?e.getCoordinates():[e.getCoordinates()];for(const t of s)for(const e of t)if(e.length>2&&isFinite(e[2]))return!0;return!1}static featureHasTime(t){const e=t&&t.getGeometry&&t.getGeometry();if(!e)return!1;return!!_(t,"MultiLineString"===e.getType()?e.getCoordinates():[e.getCoordinates()])}_buildDom(t){const e=this.options;this._applyTheme(),this._applyTransparency();const s=document.createElement("div");s.className="oep-header",this._titleEl=document.createElement("span"),this._titleEl.className="oep-title",this._titleEl.textContent=e.labels.empty,this._statsEl=document.createElement("span"),this._statsEl.className="oep-stats",s.appendChild(this._titleEl),s.appendChild(this._statsEl),this._toolbar=document.createElement("span"),this._toolbar.className="oep-toolbar";const o=(t,e,s,o)=>{const i=document.createElement("button");return i.type="button",i.className=`oep-tbtn ${t}`,i.innerHTML=e,i.title=s,i.setAttribute("aria-label",s),i.addEventListener("click",o),this._toolbar.appendChild(i),i};this._btnA=o("oep-a",'<svg viewBox="0 0 24 24"><path d="M7 5v14M11 12h8m0 0-3-3m3 3-3 3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',e.labels.zoomStart,()=>this._arm("A")),this._btnB=o("oep-b",'<svg viewBox="0 0 24 24"><path d="M17 5v14M13 12H5m0 0 3-3m-3 3 3 3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',e.labels.zoomEnd,()=>this._arm("B")),this._btnAll=o("oep-all",'<svg viewBox="0 0 24 24"><path d="M4 12h16M4 12l4-4M4 12l4 4M20 12l-4-4M20 12l-4 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',e.labels.zoomAll,()=>this._exitZoom()),s.appendChild(this._toolbar);const i=document.createElement("button");i.className="oep-toggle",i.type="button",i.setAttribute("aria-label","Réduire ou agrandir le profil"),i.innerHTML=this._collapsed?b:x,i.addEventListener("click",()=>this.toggleCollapsed()),s.appendChild(i),this._toggleBtn=i,this._legendEl=document.createElement("div"),this._legendEl.className="oep-legend",this._legendEl.style.display="none",this._body=document.createElement("div"),this._body.className="oep-body",t.appendChild(s),t.appendChild(this._legendEl),t.appendChild(this._body),this._applyCollapsable(),this._updateZoomButtons(),this._collapsed&&t.classList.add("oep-collapsed")}_resolveColor(){const t=this.options;return t.color?"auto"===t.color?this._featureColor():t.color:null}_featureColor(){const t=this._feature;if(!t)return null;const e=this.getMap()?this.getMap().getView().getResolution():1;let s=f(t.getStyle&&t.getStyle(),t,e);return!s&&this.options.trackLayer&&(s=f(this.options.trackLayer.getStyle&&this.options.trackLayer.getStyle(),t,e)),function(t){if(null==t)return null;if("string"==typeof t)return t;if(Array.isArray(t)){const e=t.length>3?t[3]:1;return`rgba(${0|t[0]},${0|t[1]},${0|t[2]},${e})`}return null}(s)}_applyTheme(){const t=this.options,e="object"==typeof t.theme?t.theme:h[t.theme]||h.steelblue;this.themeColors=e;const s=this.element,o=this._resolveColor(),i=o||e.area;let n=e.line;if(o)try{n=String(r.color(o).darker(.7))}catch(t){n=o}s.style.setProperty("--oep-area",i),s.style.setProperty("--oep-line",n),s.style.setProperty("--oep-axis",e.axis),s.style.setProperty("--oep-text",e.text),s.style.setProperty("--oep-focus",e.focus)}_applyTransparency(){const t=this.options.transparency;let e;e=!1===t||null==t?1:!0===t?this.options.transparencyLevel:Math.max(0,Math.min(1,+t)),this.element.style.setProperty("--oep-bg",`rgba(255,255,255,${e})`),this.element.classList.toggle("oep-transparent",e<1)}_applyCollapsable(){const t=this.options.collapsable;this._toggleBtn.style.display=t?"":"none",!t&&this._collapsed&&this.toggleCollapsed(!1)}toggleCollapsed(t){this._collapsed="boolean"==typeof t?t:!this._collapsed,this.element.classList.toggle("oep-collapsed",this._collapsed),this._toggleBtn.innerHTML=this._collapsed?b:x,!this._collapsed&&this._feature&&this._render(),this._adjustAttribution()}_availWidth(){const t=this.getMap(),e=t&&t.getTargetElement&&t.getTargetElement();return e&&e.clientWidth||("undefined"!=typeof window?window.innerWidth:1024)}_isMobile(){return this.options.responsive&&"undefined"!=typeof window&&window.innerWidth<=(this.options.mobileBreakpoint||640)}_applyPlacement(){const t=this._isMobile();let e=this.options.position;return t&&(e=/top/.test(e)?"top":"bottom"),this.element.className=this.element.className.replace(/oep-pos-\S+/,`oep-pos-${e}`),this.element.classList.toggle("oep-mobile",t),t}_adjustAttribution(){const t=this.getMap(),e=t&&t.getTargetElement&&t.getTargetElement(),s=e&&e.querySelector&&e.querySelector(".ol-attribution");if(!s)return;if(s.style.bottom="",s.style.right="","none"===this.element.style.display||this._collapsed)return;const o=e.getBoundingClientRect(),i=this.element.getBoundingClientRect();if(!i.height)return;const n=o.bottom-i.bottom,l=o.right-i.right;n<i.height&&l<24&&(s.style.right=`${Math.max(0,Math.round(l))}px`,s.style.bottom=`${Math.round(i.height+2*n)}px`)}setMap(t){const o=this.getMap();if(super.setMap(t),this._mapKeys&&(this._mapKeys.forEach(s.unByKey),this._mapKeys=null),o&&"undefined"!=typeof window&&window.removeEventListener("resize",this._onResize),this._marker&&!t&&this._marker.setPosition(void 0),!t)return;const i=this.options;if(i.dataProjection||(i.dataProjection=t.getView().getProjection()),i.marker&&!this._marker){const s=document.createElement("div");s.className="oep-marker",this._marker=new e({element:s,positioning:"center-center",stopEvent:!1}),t.addOverlay(this._marker)}"undefined"!=typeof window&&window.addEventListener("resize",this._onResize);const n=e=>t.forEachFeatureAtPixel(e,t=>{const e=t.getGeometry();return e&&/LineString/.test(e.getType())?t:void 0});this._mapKeys=[],this._mapKeys.push(t.on("mouseover"===i.show?"pointermove":"click",t=>{const e=n(t.pixel);e&&e!==this._feature&&this.setFeature(e)})),i.hideOnMapClick&&this._mapKeys.push(t.on("click",t=>{!n(t.pixel)&&this._feature&&this.clear()})),i.followMap&&this._mapKeys.push(t.on("pointermove",e=>{if(!this._feature||this._collapsed)return;const s=this._feature.getGeometry().getClosestPoint(e.coordinate),o=t.getPixelFromCoordinate(s);o&&(Math.hypot(o[0]-e.pixel[0],o[1]-e.pixel[1])<14?this._focusByCoord(s):this._clearFocus())})),this._mapKeys.push(t.on("moveend",()=>{this._cropMode&&this._fitRes&&t.getView().getResolution()>1.25*this._fitRes&&this._exitZoom()})),this._mapKeys.push(t.on("change:size",this._onResize))}setFeature(t){return this._feature=t||null,this._cropMode=!1,this._zoomA=null,this._zoomB=null,this._armed=null,t?(this.element.style.display="",this._compute(),this._updateZoomButtons(),this._collapsed||this._render(),this):(this._fullSamples=this._samples=null,this._clear(),this)}clear(){return this.setFeature(null)}getStats(){return this._stats}setTheme(t){return this.options.theme=t,this._applyTheme(),this._feature&&!this._collapsed&&this._render(),this}setColor(t){return this.options.color=t||null,this._applyTheme(),this._feature&&!this._collapsed&&this._render(),this}setOptions(t){return this.options=u(this.options,t||{}),t&&"slopeColors"in t&&(this.slopeColors=t.slopeColors||null),t&&(t.theme||"color"in t)&&this._applyTheme(),t&&("transparency"in t||"transparencyLevel"in t)&&this._applyTransparency(),t&&"collapsable"in t&&this._applyCollapsable(),t&&"zoom"in t&&this._updateZoomButtons(),t&&void 0!==t.width&&"number"==typeof t.width&&(this.options.width=t.width),this._feature&&(this._compute(),this._updateZoomButtons(),this._collapsed||this._render()),this}_compute(){const t=this.options,e=this._feature.getGeometry(),s="MultiLineString"===e.getType()?e.getCoordinates():[e.getCoordinates()],n=t.dataProjection||this.getMap()&&this.getMap().getView().getProjection()||"EPSG:3857",l=_(this._feature,s);this._hasTime=!!l;const a=!1!==t.ignoreStops,r=null!=t.stopSpeed?t.stopSpeed:.5,h=[];let p=0,c=null,u=-1,d=0,m=null;for(const t of s)for(const e of t){u++;const t=o.toLonLat(e,n);let s=0;c&&(s=i.getDistance(c,t),p+=s);let _=null;if(l&&null!=l[u]){const t=l[u];if(null!=m){const e=(t-m)/1e3;e>0&&(!a||s/e>=r)&&(d+=e)}_=d,m=t}c=t,h.push({x:p,z:e.length>2&&isFinite(e[2])?e[2]:0,coord:e,t:_})}t.smoothing>0&&this._smooth(h,t.smoothing);const f=this._decimate(h,t.maxPoints);this._addSlope(f),this._fullSamples=f,this._fullStats=this._statsOf(f,!0),this._samples=f,this._stats=this._fullStats}_statsOf(t,e){let s=0,o=0,i=1/0,n=-1/0,l=0;for(let e=0;e<t.length;e++){const a=t[e].z;if(a<i&&(i=a),a>n&&(n=a),e>0){const i=a-t[e-1].z;i>0?s+=i:o-=i}const r=Math.abs(t[e].slope||0);r>l&&(l=r)}const a=t.length?t[t.length-1].x-t[0].x:0,r=t.length?t[0].t:null,h=t.length?t[t.length-1].t:null;return{distance:a,duration:null!=r&&null!=h?h-r:null,ascent:s,descent:o,min:isFinite(i)?i:0,max:isFinite(n)?n:0,maxAbsSlope:l,points:t.length}}_smooth(t,e){if(!(e>0)||t.length<3)return;const s=e/2,o=t.map(t=>t.z);let i=0,n=0,l=0;for(let e=0;e<t.length;e++){const a=t[e].x;for(;i<t.length&&t[i].x<a-s;)l-=o[i],i++;for(;n<t.length&&t[n].x<=a+s;)l+=o[n],n++;t[e].z=n>i?l/(n-i):o[e]}}_decimate(t,e){const s=t=>({x:t.x,z:t.z,coord:t.coord,t:t.t});if(!e||t.length<=e)return t.map(s);const o=t.length/e,i=[];for(let n=0;n<e;n++)i.push(s(t[Math.floor(n*o)]));return i.push(s(t[t.length-1])),i}_addSlope(t){for(let e=1;e<t.length;e++){const s=t[e].x-t[e-1].x;t[e].slope=s>0?(t[e].z-t[e-1].z)/s*100:0}t.length&&(t[0].slope=t.length>1?t[1].slope:0)}_slopeScale(){const t=this.options.slopeClassSize||2.5,e=this.options.maxClasses||8,s=Math.max(1,Math.floor((this._stats.maxAbsSlope||0)/t)),o=Math.min(s,e-1),i=s>o;let n;if(this.slopeColors&&this.slopeColors.length){const t=r.interpolateRgbBasis(this.slopeColors);n=e=>t(o?e/o:0)}else{const t=r.scaleLinear().domain([0,.16,.42,.68,1]).range(["#2166ac","#27a35a","#ffe000","#f4791f","#d7191c"]).interpolate(r.interpolateRgb).clamp(!0);n=e=>String(t(o?e/o:0))}return{classSize:t,maxIdx:o,capped:i,colorByIndex:n}}_classIndex(t,e){return Math.min(e.maxIdx,Math.floor(Math.abs(t)/e.classSize))}_fmtDuration(t){if(null==t||!isFinite(t))return"";const e=this.options.labels&&this.options.labels.durationUnits||{s:"sec",m:"min",h:"h",d:"j"};if((t=Math.max(0,Math.round(t)))<60)return t+" "+e.s;if(t<3600)return Math.round(t/60)+" "+e.m;if(t<86400){let s=Math.floor(t/3600),o=Math.round(t%3600/60);return 60===o&&(s++,o=0),o?`${s} ${e.h} ${o} ${e.m}`:`${s} ${e.h}`}let s=Math.floor(t/86400),o=Math.round(t%86400/3600);return 24===o&&(s++,o=0),o?`${s} ${e.d} ${o} ${e.h}`:`${s} ${e.d}`}_renderHeader(){const t=this.options,e=this._stats,s=this._feature,o=s.get&&s.get(t.titleProperty)||"Profil",i=t.titleLink&&s.get&&s.get(t.titleLink);m(i)?this._titleEl.innerHTML=`<a href="${d(i)}" target="_blank" rel="noopener">${d(o)}</a>`:this._titleEl.textContent=o,this._titleEl.setAttribute("title",o);const n=[],l=[];if(t.headerItems.forEach(o=>{if("string"==typeof o){if("distance"===o)n.push(`<b>${g(e.distance,t.units)}</b>`),l.push(g(e.distance,t.units));else if("ascent"===o)n.push(`<span class="oep-up">${t.labels.ascent} ${y(e.ascent,t.units)}</span>`),l.push(`${t.labels.ascent} ${y(e.ascent,t.units)}`);else if("descent"===o)n.push(`<span class="oep-down">${t.labels.descent} ${y(e.descent,t.units)}</span>`),l.push(`${t.labels.descent} ${y(e.descent,t.units)}`);else if("min"===o)n.push(y(e.min,t.units)),l.push(y(e.min,t.units));else if("max"===o)n.push(y(e.max,t.units)),l.push(y(e.max,t.units));else if("minmax"===o){const s=`${y(e.min,t.units)}–${y(e.max,t.units)}`;n.push(s),l.push(s)}else if("duration"===o&&null!=e.duration){const s=this._fmtDuration(e.duration);n.push(`<span class="oep-time">${d(t.labels.duration)} ${s}</span>`),l.push(`${t.labels.duration} ${s}`)}}else if(o&&o.property){const t=s.get&&s.get(o.property);if(null==t||""===t)return;const e=o.label?`${o.label} `:"";o.asLink&&m(t)?(n.push(`${e}<a href="${d(t)}" target="_blank" rel="noopener">${d(o.linkText||o.label||t)}</a>`),l.push(`${o.label||""} ${t}`)):(n.push(d(e+t)),l.push(e+t))}}),this._statsEl.innerHTML=n.join(" · "),this._statsEl.setAttribute("title",l.join(" · ")),this._legendEl.innerHTML="",t.slope&&t.slopeLegend){const t=this._slopeScale();for(let e=0;e<=t.maxIdx;e++){const s=t.colorByIndex(e),o=t.capped&&e===t.maxIdx?`≥ ${e*t.classSize} %`:`${e*t.classSize}–${(e+1)*t.classSize} %`,i=document.createElement("span");i.className="oep-leg-it",i.innerHTML=`<i class="oep-sw" style="background:${s}"></i>${o}`,this._legendEl.appendChild(i)}this._legendEl.style.display=""}else this._legendEl.style.display="none"}_render(){const t=this.options,e=this._stats,s=this._samples;if(!s||!s.length)return;this._applyTheme();const o=this._applyPlacement();this._renderHeader();const i=t.margins,n=i.unit||"px",l=t=>"px"===n?t:t*(parseFloat(getComputedStyle(this.element).fontSize)||16),a=this._availWidth(),h="auto"===t.width||"100%"===t.width||"full"===t.width?a:Math.min("number"==typeof t.width?t.width:parseFloat(t.width)||a,a);this.element.style.width=o?"":`${h}px`;const p=this.element.clientWidth||(o?a:h),c=Math.max(220,p-16),u="number"==typeof t.height?t.height:180,d=l(i.top),m=l(i.right),_=l(i.bottom),f=l(i.left),g=Math.max(10,c-f-m),y=Math.max(10,u-d-_),x=null!=t.xTicks?t.xTicks:Math.max(2,Math.round(g/80)),b=null!=t.yTicks?t.yTicks:Math.max(2,Math.round(y/40));this._body.innerHTML="";const M=r.select(this._body).append("svg").attr("class","oep-svg").attr("width",c).attr("height",u).attr("viewBox",`0 0 ${c} ${u}`),k=M.append("g").attr("transform",`translate(${f},${d})`),v=r.scaleLinear().domain([0,e.distance]).range([0,g]),z=.1*(e.max-e.min)||10,$=r.scaleLinear().domain([e.min-z,e.max+z]).range([y,0]).nice();this._x=v,this._y=$,this._dims={innerW:g,innerH:y},t.grid&&k.append("g").attr("class","oep-grid").call(r.axisLeft($).ticks(b).tickSize(-g).tickFormat(""));const E="imperial"===t.units?1609.344:1e3;const C=r.area().x(t=>v(t.x)).y0(y).y1(t=>$(t.z));if(t.slope){const e=this._slopeScale(),o=[];let i=1;for(;i<s.length;){const t=this._classIndex(s[i].slope,e);let n=i;for(;n+1<s.length&&this._classIndex(s[n+1].slope,e)===t;)n++;k.append("path").datum(s.slice(i-1,n+1)).attr("class","oep-area-slope").attr("fill",e.colorByIndex(t)).attr("d",C),i>1&&o.push(s[i-1]),i=n+1}t.slopeSeparators&&o.forEach(t=>{k.append("line").attr("class","oep-slope-sep").attr("x1",v(t.x)).attr("x2",v(t.x)).attr("y1",$(t.z)).attr("y2",y)})}else k.append("path").datum(s).attr("class","oep-area").attr("d",C);k.append("path").datum(s).attr("class","oep-line").attr("d",r.line().x(t=>v(t.x)).y(t=>$(t.z))),k.append("g").attr("class","oep-axis oep-axis-x").attr("transform",`translate(0,${y})`).call(r.axisBottom(v).ticks(x).tickFormat(t=>(t/E).toFixed(t/E<10?1:0))),k.append("text").attr("class","oep-axis-label").attr("x",g).attr("y",y+_-4).attr("text-anchor","end").text((t=>"imperial"===t?"mi":"km")(t.units)),k.append("g").attr("class","oep-axis oep-axis-y").call(r.axisLeft($).ticks(b).tickFormat(e=>"imperial"===t.units?Math.round(3.28084*e):e)),t.zoom&&!this._cropMode&&[["A",this._zoomA],["B",this._zoomB]].forEach(([t,e])=>{if(null==e)return;const s=v(e);k.append("line").attr("class","oep-ab-line").attr("x1",s).attr("x2",s).attr("y1",0).attr("y2",y),k.append("text").attr("class","oep-ab-label").attr("x",s).attr("y",-6).attr("text-anchor","middle").text(t)});const w=k.append("g").attr("class","oep-focus").style("display","none");w.append("line").attr("class","oep-focus-line").attr("y1",0).attr("y2",y),w.append("circle").attr("class","oep-focus-dot").attr("r",4);const S=w.append("g").attr("class","oep-focus-label");S.append("rect").attr("class","oep-focus-bg"),S.append("text").attr("class","oep-focus-txt"),this._focus=w;const T=r.bisector(t=>t.x).left,B=t=>{const s=r.pointer(t,k.node())[0];return Math.max(0,Math.min(e.distance,v.invert(s)))},L=M.append("rect").attr("class","oep-overlay").attr("x",f).attr("y",d).attr("width",g).attr("height",y);L.on("mousemove",t=>{const e=B(t),o=T(s,e,1),i=s[o-1],n=s[o]||i,l=e-i.x>n.x-e?n:i;this._setFocus(l),this._marker&&this._marker.setPosition(l.coord)}).on("mouseout",()=>this._clearFocus()),L.on("click",t=>{if(!this._armed||this._cropMode)return;const e=B(t);"A"===this._armed?this._zoomA=e:this._zoomB=e,this._armed=null,this._updateZoomButtons(),null!=this._zoomA&&null!=this._zoomB?this._applyZoom():this._render()}),this._armed&&L.style("cursor","col-resize"),this._adjustAttribution()}_arm(t){this._armed=this._armed===t?null:t,this._updateZoomButtons(),this._focus&&this._render()}_updateZoomButtons(){const t=!!this.options.zoom&&!!this._feature;this._toolbar.style.display=t?"":"none";const e=this._cropMode;this._btnA.style.display=t&&!e?"":"none",this._btnB.style.display=t&&!e?"":"none",this._btnAll.style.display=t&&e?"":"none",this._btnA.classList.toggle("armed","A"===this._armed),this._btnB.classList.toggle("armed","B"===this._armed)}_applyZoom(){const t=Math.min(this._zoomA,this._zoomB),e=Math.max(this._zoomA,this._zoomB),s=this._fullSamples.filter(s=>s.x>=t&&s.x<=e);if(s.length<2)return;const o=s[0].x,i=null!=s[0].t?s[0].t:0,l=s.map(t=>({x:t.x-o,z:t.z,coord:t.coord,slope:t.slope,t:null!=t.t?t.t-i:null})),a=s.map(t=>t.coord);this._samples=l,this._stats=this._statsOf(l,!1),this._cropMode=!0,this._updateZoomButtons(),this._render();const r=this.getMap();if(r){const t=n.boundingExtent(a),e=r.getView();try{this._fitRes=e.getResolutionForExtent(t,r.getSize())}catch(t){this._fitRes=null}e.fit(t,{padding:[40,40,40,40],duration:400})}}_exitZoom(){this._cropMode=!1,this._zoomA=null,this._zoomB=null,this._armed=null,this._fitRes=null,this._samples=this._fullSamples,this._stats=this._fullStats,this._updateZoomButtons(),this._collapsed||this._render();const t=this.getMap();t&&this._feature&&t.getView().fit(this._feature.getGeometry().getExtent(),{padding:[40,40,40,40],duration:400})}_tooltipText(t){const e=this.options,s=[];return e.tooltipItems.forEach(o=>{var i;"distance"===o?s.push(g(t.x,e.units)):"elevation"===o?s.push(y(t.z,e.units)):"slope"===o?s.push(`${(i=t.slope||0)>=0?"+":""}${i.toFixed(1)} %`):"time"===o&&null!=t.t&&s.push(this._fmtDuration(t.t))}),s.join(" · ")}_setFocus(t){if(!this._focus)return;const e=this._x,s=this._y;this._focus.style("display",null),this._focus.select(".oep-focus-line").attr("x1",e(t.x)).attr("x2",e(t.x)),this._focus.select(".oep-focus-dot").attr("cx",e(t.x)).attr("cy",s(t.z));let o=s(t.z)-16;o<12&&(o=s(t.z)+22);const i=this._focus.select(".oep-focus-txt").attr("x",e(t.x)).attr("y",o).text(this._tooltipText(t)),n=i.node().getBBox();this._focus.select(".oep-focus-bg").attr("x",n.x-4).attr("y",n.y-2).attr("width",n.width+8).attr("height",n.height+4),e(t.x)+n.width/2>this._dims.innerW?i.attr("text-anchor","end"):e(t.x)-n.width/2<0?i.attr("text-anchor","start"):i.attr("text-anchor","middle")}_focusByCoord(t){const e=this._samples;if(!e)return;let s=null,o=1/0;for(const i of e){const e=i.coord[0]-t[0],n=i.coord[1]-t[1],l=e*e+n*n;l<o&&(o=l,s=i)}s&&(this._setFocus(s),this._marker&&this._marker.setPosition(s.coord))}_clearFocus(){this._focus&&this._focus.style("display","none"),this._marker&&this._marker.setPosition(void 0)}_clear(){this._body.innerHTML="",this._legendEl.innerHTML="",this._legendEl.style.display="none",this._titleEl.textContent=this.options.labels.empty,this._titleEl.removeAttribute("title"),this._statsEl.innerHTML="",this._statsEl.removeAttribute("title"),this._cropMode=!1,this._updateZoomButtons(),this._clearFocus(),this.element.style.display="none",this._adjustAttribution()}}return M.addTheme=(t,e)=>{h[t]=e},M.THEMES=h,M.POSITIONS=p,M.version="0.6.0",M});
|
|
18
|
+
*/const h={steelblue:{area:"#4682b4",line:"#3a6d96",axis:"#555",text:"#222",focus:"#e6550d"},lime:{area:"#9ccc2f",line:"#7da521",axis:"#555",text:"#222",focus:"#d62728"},purple:{area:"#9467bd",line:"#76529c",axis:"#555",text:"#222",focus:"#ff9f1c"},slate:{area:"#7c8a99",line:"#4a5560",axis:"#5a6570",text:"#26303a",focus:"#2f81f7"},graphite:{area:"#9a948c",line:"#5c574f",axis:"#5c574f",text:"#2b2823",focus:"#e07a3f"},amber:{area:"#f0a23b",line:"#c4671a",axis:"#7a5a36",text:"#3a2a16",focus:"#1f6fb2"}},c=["top","bottom","left","right","top-left","top-right","bottom-left","bottom-right"],p={immersion:"docked",position:"bottom",width:520,height:180,margins:{unit:"px",top:20,right:24,bottom:30,left:48},units:"meters",dataProjection:null,dem:"terrarium",maxPoints:2e3,smoothing:0,theme:"steelblue",color:null,trackLayer:null,transparency:!1,transparencyLevel:.45,grid:!0,slope:!1,slopeClassSize:2.5,slopeColors:null,slopeSeparators:!0,slopeLegend:!0,maxClasses:8,xTicks:null,yTicks:null,show:"click",collapsable:!0,collapsed:!1,followMap:!0,marker:!0,hideOnMapClick:!0,responsive:!0,mobileBreakpoint:640,zoom:!1,ignoreStops:!0,stopSpeed:.5,tooltipItems:["distance","elevation"],headerItems:["distance","ascent","descent","minmax"],titleProperty:"name",titleLink:null,labels:{distance:"Distance",elevation:"Altitude",slope:"Pente",ascent:"D+",descent:"D-",empty:"Cliquez un tracé",time:"Temps",duration:"Durée",durationUnits:{s:"sec",m:"min",h:"h",d:"j"},zoomStart:"Définir le début (A)",zoomEnd:"Définir la fin (B)",zoomAll:"Tout voir",loading:"Chargement du profil altimétrique"}};function u(t,e){const s={};return Object.keys(t).forEach(e=>{s[e]=t[e]}),e&&Object.keys(e).forEach(o=>{e[o]&&"object"==typeof e[o]&&!Array.isArray(e[o])&&t[o]&&"object"==typeof t[o]?s[o]=u(t[o],e[o]):s[o]=e[o]}),s}const d=t=>String(t).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"}[t])),m=t=>"string"==typeof t&&/^(https?:)?\/\/|^mailto:/i.test(t);function _(t){if(!t||!t.getCoordinates)return[];const e=t.getCoordinates();switch(t.getType()){case"LineString":case"LinearRing":return[e];case"MultiLineString":return e;case"Polygon":return e.length?[e[0]]:[];case"MultiPolygon":return e.map(t=>t[0]).filter(Boolean);default:return[]}}function f(t,e){const s=t&&t.getProperties?t.getProperties():{};let o=s.coordTimes;null==o&&s.coordinateProperties&&(o=s.coordinateProperties.times||s.coordinateProperties.coordTimes);let i=null;if(Array.isArray(o)&&(i=Array.isArray(o[0])?o.reduce((t,e)=>t.concat(e),[]):o.slice()),!i&&e){const t=[];let s=!1;for(const o of e)for(const e of o){const o=e.length>3?e[3]:null;t.push(o),null!=o&&isFinite(o)&&(s=!0)}i=s?t:null}if(!i)return null;let n=0;const l=i.map(t=>{if(null==t||""===t)return null;const e="number"==typeof t?t>1e12?t:1e3*t:Date.parse(t);return isFinite(e)?(n++,e):null});return n>=2?l:null}function g(t,e,s){let o=t;if("function"==typeof o)try{o=o(e,s)}catch(t){return null}if(Array.isArray(o)&&(o=o[0]),o&&o.getStroke){const t=o.getStroke();if(t)return t.getColor()}return null}const y=(t,e)=>{if("imperial"===e){const e=t/1609.344;return e<.2?`${Math.round(3.28084*t)} ft`:`${e.toFixed(e<10?2:1)} mi`}return t<1e3?`${Math.round(t)} m`:`${(t/1e3).toFixed(t<1e4?2:1)} km`},x=(t,e)=>"imperial"===e?`${Math.round(3.28084*t)} ft`:`${Math.round(t)} m`;const b='<svg viewBox="0 0 24 24"><path d="M5 13h14" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></svg>',M='<svg viewBox="0 0 24 24"><path d="M3 19l5-7 4 4 4-6 5 9z" fill="currentColor" opacity=".85"/></svg>',v={terrarium:{url:"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png",encoding:"terrarium",maxZoom:14,attributions:'Elevation: <a href="https://registry.opendata.aws/terrain-tiles/">Terrain Tiles</a> (AWS Open Data)'}},k={source:"terrarium",zoom:"auto",maxZoom:14,maxTiles:32,concurrency:6,tileSize:256},z={terrarium:(t,e,s)=>256*t+e+s/256-32768,mapbox:(t,e,s)=>.1*(65536*t+256*e+s)-1e4};class E{constructor(t){this.cfg=t,this.decode=z[t.encoding]||z.terrarium,this.tiles=new Map}_neighbours(t,e,s){const o=function(t,e,s,o){const i=o*Math.pow(2,s),n=Math.sin(e*Math.PI/180);return[(t+180)/360*i,(.5-Math.log((1+n)/(1-n))/(4*Math.PI))*i]}(t,e,s,this.cfg.tileSize),i=o[0]-.5,n=o[1]-.5,l=Math.floor(i),r=Math.floor(n);return{i0:l,j0:r,tx:i-l,ty:n-r}}_key(t,e,s){const o=this.cfg.tileSize,i=o*Math.pow(2,s),n=Math.min(i-1,Math.max(0,e)),l=(t%i+i)%i;return{key:s+"/"+Math.floor(l/o)+"/"+Math.floor(n/o),ii:l,jj:n}}_at(t,e,s){const o=this.cfg.tileSize,i=this._key(t,e,s),n=this.tiles.get(i.key);if(!n)return null;const l=4*(i.jj%o*o+i.ii%o);return this.decode(n[l],n[l+1],n[l+2])}sample(t,e,s){const o=this._neighbours(t,e,s),i=this._at(o.i0,o.j0,s),n=this._at(o.i0+1,o.j0,s),l=this._at(o.i0,o.j0+1,s),r=this._at(o.i0+1,o.j0+1,s);if(null==i||null==n||null==l||null==r)return null;const a=i+(n-i)*o.tx;return a+(l+(r-l)*o.tx-a)*o.ty}tilesFor(t,e){const s=new Set;for(const o of t){const t=this._neighbours(o[0],o[1],e);for(let o=0;o<2;o++)for(let i=0;i<2;i++)s.add(this._key(t.i0+o,t.j0+i,e).key)}return s}_fetch(t){const e=t.split("/"),s=this.cfg.url.replace("{z}",e[0]).replace("{x}",e[1]).replace("{y}",e[2]);return new Promise(t=>{const e=new Image;e.crossOrigin="anonymous",e.onload=()=>{try{const s=this.cfg.tileSize,o=document.createElement("canvas");o.width=s,o.height=s;const i=o.getContext("2d",{willReadFrequently:!0});i.drawImage(e,0,0,s,s),t(i.getImageData(0,0,s,s).data)}catch(e){t(null)}},e.onerror=()=>t(null),e.src=s})}load(t){const e=Array.from(t).filter(t=>!this.tiles.has(t));let s=0,o=!0;const i=()=>{if(s>=e.length)return Promise.resolve();const t=e[s++];return this._fetch(t).then(e=>(this.tiles.set(t,e),e||(o=!1),i()))},n=[];for(let t=0;t<Math.min(this.cfg.concurrency,e.length);t++)n.push(i());return Promise.all(n).then(()=>o)}}class S extends t{constructor(t){const e=u(p,t||{});-1===c.indexOf(e.position)&&(e.position="bottom");const s=function(t){const e=document.createElement("div");return e.className=`ol-elevation-profile ol-unselectable ol-control oep-pos-${t.position} oep-theme-${"string"==typeof t.theme?t.theme:"custom"}`+("floating"===t.immersion?" oep-floating":""),e}(e);super({element:s,target:t&&t.target}),this.options=e,this.slopeColors=e.slopeColors||null,this._feature=null,this._fullSamples=null,this._fullStats=null,this._samples=null,this._stats=null,this._marker=null,this._collapsed=!!e.collapsed,this._cropMode=!1,this._zoomA=null,this._zoomB=null,this._armed=null,this._fitRes=null,this._demZ=null,this._demFor=null,this._demSeq=0,this._demLoading=!1,this._onResize=()=>{this._feature&&!this._collapsed&&this._render()},this._buildDom(s),s.style.display="none"}static featureHasZ(t){const e=t&&t.getGeometry&&t.getGeometry();if(!e)return!1;for(const t of _(e))for(const e of t)if(e.length>2&&isFinite(e[2]))return!0;return!1}static featureHasTime(t){const e=t&&t.getGeometry&&t.getGeometry();return!!e&&!!f(t,_(e))}_buildDom(t){const e=this.options;this._applyTheme(),this._applyTransparency();const s=document.createElement("div");s.className="oep-header",this._titleEl=document.createElement("span"),this._titleEl.className="oep-title",this._titleEl.textContent=e.labels.empty,this._statsEl=document.createElement("span"),this._statsEl.className="oep-stats",s.appendChild(this._titleEl),s.appendChild(this._statsEl),this._toolbar=document.createElement("span"),this._toolbar.className="oep-toolbar";const o=(t,e,s,o)=>{const i=document.createElement("button");return i.type="button",i.className=`oep-tbtn ${t}`,i.innerHTML=e,i.title=s,i.setAttribute("aria-label",s),i.addEventListener("click",o),this._toolbar.appendChild(i),i};this._btnA=o("oep-a",'<svg viewBox="0 0 24 24"><path d="M7 5v14M11 12h8m0 0-3-3m3 3-3 3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',e.labels.zoomStart,()=>this._arm("A")),this._btnB=o("oep-b",'<svg viewBox="0 0 24 24"><path d="M17 5v14M13 12H5m0 0 3-3m-3 3 3 3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',e.labels.zoomEnd,()=>this._arm("B")),this._btnAll=o("oep-all",'<svg viewBox="0 0 24 24"><path d="M4 12h16M4 12l4-4M4 12l4 4M20 12l-4-4M20 12l-4 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',e.labels.zoomAll,()=>this._exitZoom()),s.appendChild(this._toolbar);const i=document.createElement("button");i.className="oep-toggle",i.type="button",i.setAttribute("aria-label","Réduire ou agrandir le profil"),i.innerHTML=this._collapsed?M:b,i.addEventListener("click",()=>this.toggleCollapsed()),s.appendChild(i),this._toggleBtn=i,this._legendEl=document.createElement("div"),this._legendEl.className="oep-legend",this._legendEl.style.display="none",this._body=document.createElement("div"),this._body.className="oep-body",t.appendChild(s),t.appendChild(this._legendEl),t.appendChild(this._body),this._applyCollapsable(),this._updateZoomButtons(),this._collapsed&&t.classList.add("oep-collapsed")}_resolveColor(){const t=this.options;return t.color?"auto"===t.color?this._featureColor():t.color:null}_featureColor(){const t=this._feature;if(!t)return null;const e=this.getMap()?this.getMap().getView().getResolution():1;let s=g(t.getStyle&&t.getStyle(),t,e);return!s&&this.options.trackLayer&&(s=g(this.options.trackLayer.getStyle&&this.options.trackLayer.getStyle(),t,e)),function(t){if(null==t)return null;if("string"==typeof t)return t;if(Array.isArray(t)){const e=t.length>3?t[3]:1;return`rgba(${0|t[0]},${0|t[1]},${0|t[2]},${e})`}return null}(s)}_applyTheme(){const t=this.options,e="object"==typeof t.theme?t.theme:h[t.theme]||h.steelblue;this.themeColors=e;const s=this.element,o=this._resolveColor(),i=o||e.area;let n=e.line;if(o)try{n=String(a.color(o).darker(.7))}catch(t){n=o}s.style.setProperty("--oep-area",i),s.style.setProperty("--oep-line",n),s.style.setProperty("--oep-axis",e.axis),s.style.setProperty("--oep-text",e.text),s.style.setProperty("--oep-focus",e.focus)}_applyTransparency(){const t=this.options.transparency;let e;e=!1===t||null==t?1:!0===t?this.options.transparencyLevel:Math.max(0,Math.min(1,+t)),this.element.style.setProperty("--oep-bg",`rgba(255,255,255,${e})`),this.element.classList.toggle("oep-transparent",e<1)}_applyCollapsable(){const t=this.options.collapsable;this._toggleBtn.style.display=t?"":"none",!t&&this._collapsed&&this.toggleCollapsed(!1)}toggleCollapsed(t){this._collapsed="boolean"==typeof t?t:!this._collapsed,this.element.classList.toggle("oep-collapsed",this._collapsed),this._toggleBtn.innerHTML=this._collapsed?M:b,!this._collapsed&&this._feature&&this._render(),this._adjustAttribution()}_availWidth(){const t=this.getMap(),e=t&&t.getTargetElement&&t.getTargetElement();return e&&e.clientWidth||("undefined"!=typeof window?window.innerWidth:1024)}_isMobile(){return this.options.responsive&&"undefined"!=typeof window&&window.innerWidth<=(this.options.mobileBreakpoint||640)}_applyPlacement(){const t=this._isMobile();let e=this.options.position;return t&&(e=/top/.test(e)?"top":"bottom"),this.element.className=this.element.className.replace(/oep-pos-\S+/,`oep-pos-${e}`),this.element.classList.toggle("oep-mobile",t),t}_adjustAttribution(){const t=this.getMap(),e=t&&t.getTargetElement&&t.getTargetElement(),s=e&&e.querySelector&&e.querySelector(".ol-attribution");if(!s)return;if(s.style.bottom="",s.style.right="","none"===this.element.style.display||this._collapsed)return;const o=e.getBoundingClientRect(),i=this.element.getBoundingClientRect();if(!i.height)return;const n=o.bottom-i.bottom,l=o.right-i.right;n<i.height&&l<24&&(s.style.right=`${Math.max(0,Math.round(l))}px`,s.style.bottom=`${Math.round(i.height+2*n)}px`)}setMap(t){const o=this.getMap();if(super.setMap(t),this._mapKeys&&(this._mapKeys.forEach(s.unByKey),this._mapKeys=null),o&&"undefined"!=typeof window&&window.removeEventListener("resize",this._onResize),this._marker&&!t&&this._marker.setPosition(void 0),!t)return;const i=this.options;if(i.dataProjection||(i.dataProjection=t.getView().getProjection()),i.marker&&!this._marker){const s=document.createElement("div");s.className="oep-marker",this._marker=new e({element:s,positioning:"center-center",stopEvent:!1}),t.addOverlay(this._marker)}"undefined"!=typeof window&&window.addEventListener("resize",this._onResize);const n=e=>t.forEachFeatureAtPixel(e,t=>{const e=t.getGeometry();return(s=e)&&/^(Multi)?(LineString|Polygon)$|^LinearRing$/.test(s.getType())?t:void 0;var s});this._mapKeys=[],this._mapKeys.push(t.on("mouseover"===i.show?"pointermove":"click",t=>{const e=n(t.pixel);e&&e!==this._feature&&this.setFeature(e)})),i.hideOnMapClick&&this._mapKeys.push(t.on("click",t=>{!n(t.pixel)&&this._feature&&this.clear()})),i.followMap&&this._mapKeys.push(t.on("pointermove",e=>{if(!this._feature||this._collapsed)return;const s=this._closestOnProfile(e.coordinate);if(!s)return;const o=t.getPixelFromCoordinate(s);o&&(Math.hypot(o[0]-e.pixel[0],o[1]-e.pixel[1])<14?this._focusByCoord(s):this._clearFocus())})),this._mapKeys.push(t.on("moveend",()=>{this._cropMode&&this._fitRes&&t.getView().getResolution()>1.25*this._fitRes&&this._exitZoom()})),this._mapKeys.push(t.on("change:size",this._onResize))}setFeature(t){return this._feature=t||null,this._cropMode=!1,this._zoomA=null,this._zoomB=null,this._armed=null,t?(this.element.style.display="",this._compute(),this._fillFromDem(t),this._updateZoomButtons(),this._collapsed?this._renderTitle():this._render(),this):(this._fullSamples=this._samples=null,this._demZ=this._demFor=null,this._clear(),this)}clear(){return this.setFeature(null)}getStats(){return this._stats}setTheme(t){return this.options.theme=t,this._applyTheme(),this._feature&&!this._collapsed&&this._render(),this}setColor(t){return this.options.color=t||null,this._applyTheme(),this._feature&&!this._collapsed&&this._render(),this}setOptions(t){return this.options=u(this.options,t||{}),t&&"slopeColors"in t&&(this.slopeColors=t.slopeColors||null),t&&(t.theme||"color"in t)&&this._applyTheme(),t&&("transparency"in t||"transparencyLevel"in t)&&this._applyTransparency(),t&&"collapsable"in t&&this._applyCollapsable(),t&&"zoom"in t&&this._updateZoomButtons(),t&&void 0!==t.width&&"number"==typeof t.width&&(this.options.width=t.width),t&&"dem"in t&&(this._demZ=null,this._demFor=null),this._feature&&(this._compute(),this._fillFromDem(this._feature),this._updateZoomButtons(),this._collapsed?this._renderTitle():this._render()),this}_fillFromDem(t){const e=function(t){if(!t)return null;const e=!0===t||"string"==typeof t?{source:!0===t?"terrarium":t}:Object.assign({},t),s=v[e.source]||(e.url?{}:v.terrarium),o=Object.assign({},k,s,e);return o.url?o:null}(this.options.dem);if(!e||!t||this._demFor===t)return;if(S.featureHasZ(t))return;if("undefined"==typeof Image||"undefined"==typeof document)return;const s=t.getGeometry&&t.getGeometry();if(!s)return;const i=_(s),n=this.options.dataProjection||this.getMap()&&this.getMap().getView().getProjection()||"EPSG:3857",l=[];for(const t of i)for(const e of t)l.push(o.toLonLat(e,n));if(!l.length)return;const r=++this._demSeq,a=new E(e),h=function(t,e,s){if("number"==typeof s.zoom)return s.zoom;for(let o=s.maxZoom;o>0;o--)if(t.tilesFor(e,o).size<=s.maxTiles)return o;return 1}(a,l,e);this._demLoading=!0,a.load(a.tilesFor(l,h)).then(e=>{if(r!==this._demSeq||this._feature!==t)return;const s=e?l.map(t=>a.sample(t[0],t[1],h)):null,o=!!s&&s.every(t=>null!=t&&isFinite(t));this._demLoading=!1,o&&(this._demZ=s,this._demFor=t,this._compute()),this._updateZoomButtons(),this._collapsed||this._render(),this.dispatchEvent({type:"demload",ok:o,zoom:h,tiles:a.tiles.size})})}_compute(){const t=this.options,e=_(this._feature.getGeometry()),s=t.dataProjection||this.getMap()&&this.getMap().getView().getProjection()||"EPSG:3857",n=this._demFor===this._feature?this._demZ:null,l=f(this._feature,e);this._hasTime=!!l;const r=!1!==t.ignoreStops,a=null!=t.stopSpeed?t.stopSpeed:.5,h=[];let c=0,p=null,u=-1,d=0,m=null;for(const t of e)for(const e of t){u++;const t=o.toLonLat(e,s);let _=0;p&&(_=i.getDistance(p,t),c+=_);let f=null;if(l&&null!=l[u]){const t=l[u];if(null!=m){const e=(t-m)/1e3;e>0&&(!r||_/e>=a)&&(d+=e)}f=d,m=t}p=t;const g=e.length>2&&isFinite(e[2])?e[2]:n?n[u]:0;h.push({x:c,z:g,coord:e,t:f})}t.smoothing>0&&this._smooth(h,t.smoothing);const g=this._decimate(h,t.maxPoints);this._addSlope(g),this._fullSamples=g,this._fullStats=this._statsOf(g,!0),this._samples=g,this._stats=this._fullStats}_statsOf(t,e){let s=0,o=0,i=1/0,n=-1/0,l=0;for(let e=0;e<t.length;e++){const r=t[e].z;if(r<i&&(i=r),r>n&&(n=r),e>0){const i=r-t[e-1].z;i>0?s+=i:o-=i}const a=Math.abs(t[e].slope||0);a>l&&(l=a)}const r=t.length?t[t.length-1].x-t[0].x:0,a=t.length?t[0].t:null,h=t.length?t[t.length-1].t:null;return{distance:r,duration:null!=a&&null!=h?h-a:null,ascent:s,descent:o,min:isFinite(i)?i:0,max:isFinite(n)?n:0,maxAbsSlope:l,points:t.length}}_smooth(t,e){if(!(e>0)||t.length<3)return;const s=e/2,o=t.map(t=>t.z);let i=0,n=0,l=0;for(let e=0;e<t.length;e++){const r=t[e].x;for(;i<t.length&&t[i].x<r-s;)l-=o[i],i++;for(;n<t.length&&t[n].x<=r+s;)l+=o[n],n++;t[e].z=n>i?l/(n-i):o[e]}}_decimate(t,e){const s=t=>({x:t.x,z:t.z,coord:t.coord,t:t.t});if(!e||t.length<=e)return t.map(s);const o=t.length/e,i=[];for(let n=0;n<e;n++)i.push(s(t[Math.floor(n*o)]));return i.push(s(t[t.length-1])),i}_addSlope(t){for(let e=1;e<t.length;e++){const s=t[e].x-t[e-1].x;t[e].slope=s>0?(t[e].z-t[e-1].z)/s*100:0}t.length&&(t[0].slope=t.length>1?t[1].slope:0)}_slopeScale(){const t=this.options.slopeClassSize||2.5,e=this.options.maxClasses||8,s=Math.max(1,Math.floor((this._stats.maxAbsSlope||0)/t)),o=Math.min(s,e-1),i=s>o;let n;if(this.slopeColors&&this.slopeColors.length){const t=a.interpolateRgbBasis(this.slopeColors);n=e=>t(o?e/o:0)}else{const t=a.scaleLinear().domain([0,.16,.42,.68,1]).range(["#2166ac","#27a35a","#ffe000","#f4791f","#d7191c"]).interpolate(a.interpolateRgb).clamp(!0);n=e=>String(t(o?e/o:0))}return{classSize:t,maxIdx:o,capped:i,colorByIndex:n}}_classIndex(t,e){return Math.min(e.maxIdx,Math.floor(Math.abs(t)/e.classSize))}_fmtDuration(t){if(null==t||!isFinite(t))return"";const e=this.options.labels&&this.options.labels.durationUnits||{s:"sec",m:"min",h:"h",d:"j"};if((t=Math.max(0,Math.round(t)))<60)return t+" "+e.s;if(t<3600)return Math.round(t/60)+" "+e.m;if(t<86400){let s=Math.floor(t/3600),o=Math.round(t%3600/60);return 60===o&&(s++,o=0),o?`${s} ${e.h} ${o} ${e.m}`:`${s} ${e.h}`}let s=Math.floor(t/86400),o=Math.round(t%86400/3600);return 24===o&&(s++,o=0),o?`${s} ${e.d} ${o} ${e.h}`:`${s} ${e.d}`}_renderTitle(){const t=this.options,e=this._feature;if(!e)return;const s=e.get&&e.get(t.titleProperty)||"Profil",o=t.titleLink&&e.get&&e.get(t.titleLink);m(o)?this._titleEl.innerHTML=`<a href="${d(o)}" target="_blank" rel="noopener">${d(s)}</a>`:this._titleEl.textContent=s,this._titleEl.setAttribute("title",s)}_renderHeader(){const t=this.options,e=this._stats,s=this._feature;if(this._renderTitle(),this._demLoading)return this._statsEl.innerHTML="",this._statsEl.removeAttribute("title"),this._legendEl.innerHTML="",void(this._legendEl.style.display="none");const o=[],i=[];if(t.headerItems.forEach(n=>{if("string"==typeof n){if("distance"===n)o.push(`<b>${y(e.distance,t.units)}</b>`),i.push(y(e.distance,t.units));else if("ascent"===n)o.push(`<span class="oep-up">${t.labels.ascent} ${x(e.ascent,t.units)}</span>`),i.push(`${t.labels.ascent} ${x(e.ascent,t.units)}`);else if("descent"===n)o.push(`<span class="oep-down">${t.labels.descent} ${x(e.descent,t.units)}</span>`),i.push(`${t.labels.descent} ${x(e.descent,t.units)}`);else if("min"===n)o.push(x(e.min,t.units)),i.push(x(e.min,t.units));else if("max"===n)o.push(x(e.max,t.units)),i.push(x(e.max,t.units));else if("minmax"===n){const s=`${x(e.min,t.units)}–${x(e.max,t.units)}`;o.push(s),i.push(s)}else if("duration"===n&&null!=e.duration){const s=this._fmtDuration(e.duration);o.push(`<span class="oep-time">${d(t.labels.duration)} ${s}</span>`),i.push(`${t.labels.duration} ${s}`)}}else if(n&&n.property){const t=s.get&&s.get(n.property);if(null==t||""===t)return;const e=n.label?`${n.label} `:"";n.asLink&&m(t)?(o.push(`${e}<a href="${d(t)}" target="_blank" rel="noopener">${d(n.linkText||n.label||t)}</a>`),i.push(`${n.label||""} ${t}`)):(o.push(d(e+t)),i.push(e+t))}}),this._statsEl.innerHTML=o.join(" · "),this._statsEl.setAttribute("title",i.join(" · ")),this._legendEl.innerHTML="",t.slope&&t.slopeLegend){const t=this._slopeScale();for(let e=0;e<=t.maxIdx;e++){const s=t.colorByIndex(e),o=t.capped&&e===t.maxIdx?`≥ ${e*t.classSize} %`:`${e*t.classSize}–${(e+1)*t.classSize} %`,i=document.createElement("span");i.className="oep-leg-it",i.innerHTML=`<i class="oep-sw" style="background:${s}"></i>${o}`,this._legendEl.appendChild(i)}this._legendEl.style.display=""}else this._legendEl.style.display="none"}_renderSpinner(){const t="number"==typeof this.options.height?this.options.height:180;this._body.innerHTML="";const e=document.createElement("div");e.className="oep-loading",e.style.height=`${t}px`,e.setAttribute("role","status"),e.setAttribute("aria-label",this.options.labels.loading);const s=document.createElement("div");s.className="oep-spinner",e.appendChild(s),this._body.appendChild(e)}_render(){const t=this.options,e=this._stats,s=this._samples;if(!s||!s.length)return;this._applyTheme();const o=this._applyPlacement();if(this._renderHeader(),this._demLoading)return void this._renderSpinner();const i=t.margins,n=i.unit||"px",l=t=>"px"===n?t:t*(parseFloat(getComputedStyle(this.element).fontSize)||16),r=this._availWidth(),h="auto"===t.width||"100%"===t.width||"full"===t.width?r:Math.min("number"==typeof t.width?t.width:parseFloat(t.width)||r,r);this.element.style.width=o?"":`${h}px`;const c=this.element.clientWidth||(o?r:h),p=Math.max(220,c-16),u="number"==typeof t.height?t.height:180,d=l(i.top),m=l(i.right),_=l(i.bottom),f=l(i.left),g=Math.max(10,p-f-m),y=Math.max(10,u-d-_),x=null!=t.xTicks?t.xTicks:Math.max(2,Math.round(g/80)),b=null!=t.yTicks?t.yTicks:Math.max(2,Math.round(y/40));this._body.innerHTML="";const M=a.select(this._body).append("svg").attr("class","oep-svg").attr("width",p).attr("height",u).attr("viewBox",`0 0 ${p} ${u}`),v=M.append("g").attr("transform",`translate(${f},${d})`),k=a.scaleLinear().domain([0,e.distance]).range([0,g]),z=.1*(e.max-e.min)||10,E=a.scaleLinear().domain([e.min-z,e.max+z]).range([y,0]).nice();this._x=k,this._y=E,this._dims={innerW:g,innerH:y},t.grid&&v.append("g").attr("class","oep-grid").call(a.axisLeft(E).ticks(b).tickSize(-g).tickFormat(""));const S="imperial"===t.units?1609.344:1e3;const w=a.area().x(t=>k(t.x)).y0(y).y1(t=>E(t.z));if(t.slope){const e=this._slopeScale(),o=[];let i=1;for(;i<s.length;){const t=this._classIndex(s[i].slope,e);let n=i;for(;n+1<s.length&&this._classIndex(s[n+1].slope,e)===t;)n++;v.append("path").datum(s.slice(i-1,n+1)).attr("class","oep-area-slope").attr("fill",e.colorByIndex(t)).attr("d",w),i>1&&o.push(s[i-1]),i=n+1}t.slopeSeparators&&o.forEach(t=>{v.append("line").attr("class","oep-slope-sep").attr("x1",k(t.x)).attr("x2",k(t.x)).attr("y1",E(t.z)).attr("y2",y)})}else v.append("path").datum(s).attr("class","oep-area").attr("d",w);v.append("path").datum(s).attr("class","oep-line").attr("d",a.line().x(t=>k(t.x)).y(t=>E(t.z))),v.append("g").attr("class","oep-axis oep-axis-x").attr("transform",`translate(0,${y})`).call(a.axisBottom(k).ticks(x).tickFormat(t=>(t/S).toFixed(t/S<10?1:0))),v.append("text").attr("class","oep-axis-label").attr("x",g).attr("y",y+_-4).attr("text-anchor","end").text((t=>"imperial"===t?"mi":"km")(t.units)),v.append("g").attr("class","oep-axis oep-axis-y").call(a.axisLeft(E).ticks(b).tickFormat(e=>"imperial"===t.units?Math.round(3.28084*e):e)),t.zoom&&!this._cropMode&&[["A",this._zoomA],["B",this._zoomB]].forEach(([t,e])=>{if(null==e)return;const s=k(e);v.append("line").attr("class","oep-ab-line").attr("x1",s).attr("x2",s).attr("y1",0).attr("y2",y),v.append("text").attr("class","oep-ab-label").attr("x",s).attr("y",-6).attr("text-anchor","middle").text(t)});const $=v.append("g").attr("class","oep-focus").style("display","none");$.append("line").attr("class","oep-focus-line").attr("y1",0).attr("y2",y),$.append("circle").attr("class","oep-focus-dot").attr("r",4);const C=$.append("g").attr("class","oep-focus-label");C.append("rect").attr("class","oep-focus-bg"),C.append("text").attr("class","oep-focus-txt"),this._focus=$;const T=a.bisector(t=>t.x).left,j=t=>{const s=a.pointer(t,v.node())[0];return Math.max(0,Math.min(e.distance,k.invert(s)))},L=M.append("rect").attr("class","oep-overlay").attr("x",f).attr("y",d).attr("width",g).attr("height",y);L.on("mousemove",t=>{const e=j(t),o=T(s,e,1),i=s[o-1],n=s[o]||i,l=e-i.x>n.x-e?n:i;this._setFocus(l),this._marker&&this._marker.setPosition(l.coord)}).on("mouseout",()=>this._clearFocus()),L.on("click",t=>{if(!this._armed||this._cropMode)return;const e=j(t);"A"===this._armed?this._zoomA=e:this._zoomB=e,this._armed=null,this._updateZoomButtons(),null!=this._zoomA&&null!=this._zoomB?this._applyZoom():this._render()}),this._armed&&L.style("cursor","col-resize"),this._adjustAttribution()}_arm(t){this._armed=this._armed===t?null:t,this._updateZoomButtons(),this._focus&&this._render()}_updateZoomButtons(){const t=!!this.options.zoom&&!!this._feature;this._toolbar.style.display=t?"":"none";const e=this._cropMode;this._btnA.style.display=t&&!e?"":"none",this._btnB.style.display=t&&!e?"":"none",this._btnAll.style.display=t&&e?"":"none",this._btnA.classList.toggle("armed","A"===this._armed),this._btnB.classList.toggle("armed","B"===this._armed)}_applyZoom(){const t=Math.min(this._zoomA,this._zoomB),e=Math.max(this._zoomA,this._zoomB),s=this._fullSamples.filter(s=>s.x>=t&&s.x<=e);if(s.length<2)return;const o=s[0].x,i=null!=s[0].t?s[0].t:0,l=s.map(t=>({x:t.x-o,z:t.z,coord:t.coord,slope:t.slope,t:null!=t.t?t.t-i:null})),r=s.map(t=>t.coord);this._samples=l,this._stats=this._statsOf(l,!1),this._cropMode=!0,this._updateZoomButtons(),this._render();const a=this.getMap();if(a){const t=n.boundingExtent(r),e=a.getView();try{this._fitRes=e.getResolutionForExtent(t,a.getSize())}catch(t){this._fitRes=null}e.fit(t,{padding:[40,40,40,40],duration:400})}}_exitZoom(){this._cropMode=!1,this._zoomA=null,this._zoomB=null,this._armed=null,this._fitRes=null,this._samples=this._fullSamples,this._stats=this._fullStats,this._updateZoomButtons(),this._collapsed||this._render();const t=this.getMap();t&&this._feature&&t.getView().fit(this._feature.getGeometry().getExtent(),{padding:[40,40,40,40],duration:400})}_closestOnProfile(t){const e=this._feature&&this._feature.getGeometry();if(!e)return null;if(!/Polygon/.test(e.getType()))return e.getClosestPoint(t);const s=this._fullSamples;if(!s||!s.length)return null;let o=null,i=1/0;for(const e of s){const s=e.coord[0]-t[0],n=e.coord[1]-t[1],l=s*s+n*n;l<i&&(i=l,o=e.coord)}return o}_tooltipText(t){const e=this.options,s=[];return e.tooltipItems.forEach(o=>{var i;"distance"===o?s.push(y(t.x,e.units)):"elevation"===o?s.push(x(t.z,e.units)):"slope"===o?s.push(`${(i=t.slope||0)>=0?"+":""}${i.toFixed(1)} %`):"time"===o&&null!=t.t&&s.push(this._fmtDuration(t.t))}),s.join(" · ")}_setFocus(t){if(!this._focus)return;const e=this._x,s=this._y;this._focus.style("display",null),this._focus.select(".oep-focus-line").attr("x1",e(t.x)).attr("x2",e(t.x)),this._focus.select(".oep-focus-dot").attr("cx",e(t.x)).attr("cy",s(t.z));let o=s(t.z)-16;o<12&&(o=s(t.z)+22);const i=this._focus.select(".oep-focus-txt").attr("x",e(t.x)).attr("y",o).text(this._tooltipText(t)),n=i.node().getBBox();this._focus.select(".oep-focus-bg").attr("x",n.x-4).attr("y",n.y-2).attr("width",n.width+8).attr("height",n.height+4),e(t.x)+n.width/2>this._dims.innerW?i.attr("text-anchor","end"):e(t.x)-n.width/2<0?i.attr("text-anchor","start"):i.attr("text-anchor","middle")}_focusByCoord(t){const e=this._samples;if(!e)return;let s=null,o=1/0;for(const i of e){const e=i.coord[0]-t[0],n=i.coord[1]-t[1],l=e*e+n*n;l<o&&(o=l,s=i)}s&&(this._setFocus(s),this._marker&&this._marker.setPosition(s.coord))}_clearFocus(){this._focus&&this._focus.style("display","none"),this._marker&&this._marker.setPosition(void 0)}_clear(){this._body.innerHTML="",this._legendEl.innerHTML="",this._legendEl.style.display="none",this._titleEl.textContent=this.options.labels.empty,this._titleEl.removeAttribute("title"),this._statsEl.innerHTML="",this._statsEl.removeAttribute("title"),this._cropMode=!1,this._demLoading=!1,this._updateZoomButtons(),this._clearFocus(),this.element.style.display="none",this._adjustAttribution()}}return S.addTheme=(t,e)=>{h[t]=e},S.THEMES=h,S.DEM_PRESETS=v,S.DemSampler=E,S.POSITIONS=c,S.version="0.6.0",S});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ol-elevation-profile",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Synchronized elevation profile control for OpenLayers, rendered with d3. Reads elevation
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Synchronized elevation profile control for OpenLayers, rendered with d3. Reads elevation from 3D GPX/GeoJSON geometries, and fills it from keyless terrain tiles when they have none.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/ol-elevation-profile.js",
|
|
7
7
|
"module": "dist/ol-elevation-profile.esm.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "rollup -c && cp src/ol-elevation-profile.css dist/ol-elevation-profile.css",
|
|
35
35
|
"prepublishOnly": "npm run build",
|
|
36
|
-
"test": "node test/smoke.
|
|
36
|
+
"test": "node test/smoke.cjs",
|
|
37
37
|
"docs:dev": "vitepress dev docs",
|
|
38
38
|
"docs:build": "vitepress build docs",
|
|
39
39
|
"docs:preview": "vitepress preview docs"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
}
|
|
22
22
|
.ol-elevation-profile.oep-transparent { backdrop-filter: blur(2px); }
|
|
23
23
|
|
|
24
|
-
/* ---- 8
|
|
24
|
+
/* ---- 8 anchors ---- */
|
|
25
25
|
.ol-elevation-profile.oep-pos-bottom { left: 50%; bottom: .6em; transform: translateX(-50%); }
|
|
26
26
|
.ol-elevation-profile.oep-pos-top { left: 50%; top: .6em; transform: translateX(-50%); }
|
|
27
27
|
.ol-elevation-profile.oep-pos-left { left: .6em; top: 50%; transform: translateY(-50%); }
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
.ol-elevation-profile.oep-pos-bottom-left { left: .6em; bottom: .6em; }
|
|
32
32
|
.ol-elevation-profile.oep-pos-bottom-right { right: .6em; bottom: .6em; }
|
|
33
33
|
|
|
34
|
-
/* ---- mobile
|
|
34
|
+
/* ---- mobile: full width, pinned to the top or the bottom ---- */
|
|
35
35
|
.ol-elevation-profile.oep-mobile { left: 0 !important; right: 0 !important; width: auto !important; transform: none !important; }
|
|
36
36
|
.ol-elevation-profile.oep-mobile.oep-pos-bottom { bottom: 0; border-radius: 10px 10px 0 0; }
|
|
37
37
|
.ol-elevation-profile.oep-mobile.oep-pos-top { top: 0; border-radius: 0 0 10px 10px; }
|
|
38
38
|
|
|
39
|
-
/* ----
|
|
39
|
+
/* ---- header ---- */
|
|
40
40
|
.oep-header { display: flex; align-items: center; gap: 8px; width: 100%; padding: 0 2px 2px; }
|
|
41
41
|
.oep-title { flex: 0 1 auto; min-width: 0; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
42
42
|
.oep-title a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
.oep-stats .oep-up { color: #c0392b; }
|
|
46
46
|
.oep-stats .oep-down { color: #2471a3; }
|
|
47
47
|
|
|
48
|
-
/* ----
|
|
48
|
+
/* ---- zoom toolbar ---- */
|
|
49
49
|
.oep-toolbar { flex: 0 0 auto; display: inline-flex; gap: 2px; margin-left: auto; }
|
|
50
50
|
.oep-tbtn {
|
|
51
51
|
display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 22px;
|
|
@@ -65,14 +65,14 @@
|
|
|
65
65
|
.oep-toggle:hover { opacity: 1; background: rgba(0, 0, 0, .07); }
|
|
66
66
|
.oep-toggle svg { width: 15px; height: 15px; display: block; }
|
|
67
67
|
|
|
68
|
-
/* ----
|
|
68
|
+
/* ---- slope legend ---- */
|
|
69
69
|
.oep-legend { display: flex; flex-wrap: wrap; gap: 4px 10px; padding: 0 2px 4px; font-size: 10px; opacity: .9; }
|
|
70
70
|
.oep-leg-it { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
|
|
71
71
|
.oep-sw { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
|
|
72
72
|
|
|
73
73
|
.oep-body { overflow: hidden; }
|
|
74
74
|
|
|
75
|
-
/* ---- mode
|
|
75
|
+
/* ---- collapsed mode: the control shrinks to title + button width ---- */
|
|
76
76
|
.ol-elevation-profile.oep-collapsed { width: auto !important; }
|
|
77
77
|
.ol-elevation-profile.oep-collapsed .oep-body,
|
|
78
78
|
.ol-elevation-profile.oep-collapsed .oep-legend { display: none !important; }
|
|
@@ -80,6 +80,22 @@
|
|
|
80
80
|
.ol-elevation-profile.oep-collapsed .oep-toolbar { display: none !important; }
|
|
81
81
|
.ol-elevation-profile.oep-collapsed .oep-header { width: auto; }
|
|
82
82
|
|
|
83
|
+
/* ---- terrain-model loading spinner ---- */
|
|
84
|
+
/* Takes --oep-area, so it wears the theme colour - and the track colour under color:'auto'. */
|
|
85
|
+
.oep-loading { display: flex; align-items: center; justify-content: center; }
|
|
86
|
+
.oep-spinner {
|
|
87
|
+
width: 26px; height: 26px; box-sizing: border-box;
|
|
88
|
+
border: 3px solid var(--oep-area);
|
|
89
|
+
border-top-color: transparent;
|
|
90
|
+
border-radius: 50%;
|
|
91
|
+
opacity: .9;
|
|
92
|
+
animation: oep-spin .8s linear infinite;
|
|
93
|
+
}
|
|
94
|
+
@keyframes oep-spin { to { transform: rotate(360deg); } }
|
|
95
|
+
/* A still ring reads as a broken control rather than a wait, so the motion stays -
|
|
96
|
+
slowed to a crawl, which is what the reduced-motion request is really about. */
|
|
97
|
+
@media (prefers-reduced-motion: reduce) { .oep-spinner { animation-duration: 4s; } }
|
|
98
|
+
|
|
83
99
|
/* ---- chart ---- */
|
|
84
100
|
.oep-svg { display: block; }
|
|
85
101
|
.oep-area { fill: var(--oep-area); opacity: .6; }
|