@geoblocks/elevation-profile 0.0.16 → 0.0.18

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.
@@ -0,0 +1,44 @@
1
+ import { LitElement, PropertyValues, TemplateResult } from "lit";
2
+ export type OverDetails = {
3
+ coordinate: number[];
4
+ position: {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ };
9
+ export default class ElevationProfile extends LitElement {
10
+ tolerance: number;
11
+ locale: string;
12
+ lines: number[][][];
13
+ points: number[][];
14
+ updateScale: (x: scaleLinear, y: scaleLinear, width: number, height: number) => void;
15
+ margin: {
16
+ top: number;
17
+ right: number;
18
+ bottom: number;
19
+ left: number;
20
+ };
21
+ tickSize: {
22
+ x: number;
23
+ y: number;
24
+ };
25
+ pointerEvents: boolean;
26
+ pointer: {
27
+ x: number;
28
+ y: number;
29
+ };
30
+ updated(changedProperties: PropertyValues): void;
31
+ willUpdate(changedProperties: PropertyValues): void;
32
+ render(): TemplateResult<2>;
33
+ tickFormat(value: number, axis: 'x' | 'y'): string;
34
+ pointSvg(x: number, y: number, index: number): TemplateResult;
35
+ firstUpdated(): void;
36
+ createRenderRoot(): this;
37
+ }
38
+ declare global {
39
+ interface HTMLElementTagNameMap {
40
+ 'elevation-profile': ElevationProfile;
41
+ }
42
+ }
43
+
44
+ //# sourceMappingURL=elevation-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"mappings":";AAoBA,0BAA0B;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC;CAClC,CAAC;AAEF,qCACsC,SAAQ,UAAU;IAC5B,SAAS,SAAK;IACd,MAAM,SAAsB;IAC7B,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAM;IACzB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAM;IACrC,WAAW,0CAA2C,MAAM,UAAU,MAAM,KAAG,IAAI,CAAO;IAC5E,MAAM;;;;;MAA8C;IACpD,QAAQ;;;MAAmB;IAC1B,aAAa,UAAQ;IAEvC,OAAO;;;MAAgB;IA4BvB,OAAO,CAAC,iBAAiB,EAAE,cAAc;IAczC,UAAU,CAAC,iBAAiB,EAAE,cAAc;IAsB5C,MAAM;IAyER,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG;IAQzC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc;IAI3D,YAAY;IA+CZ,gBAAgB;CAG1B;AAGD,QAAQ,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,gBAAgB,CAAC;KACvC;CACF","sources":["elevation-profile.ts"],"sourcesContent":["import {LitElement, svg} from 'lit';\nimport {customElement, state, property} from 'lit/decorators.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport {guard} from 'lit/directives/guard.js';\nimport type {PropertyValues, TemplateResult} from 'lit';\n\nimport {extent, bisector} from 'd3-array';\nimport {scaleLinear} from 'd3-scale';\nimport {line, area} from 'd3-shape';\nimport {axisBottom, axisLeft} from 'd3-axis';\nimport {select, pointer} from 'd3-selection';\n\nimport simplify from 'simplify-js';\n\ntype PlotPoint = {\n x: number;\n y: number;\n coordinate: number[];\n};\n\nexport type OverDetails = {\n coordinate: number[];\n position: {x: number; y: number};\n};\n\n@customElement('elevation-profile')\nexport default class ElevationProfile extends LitElement {\n @property({type: Number}) tolerance = 1;\n @property({type: String}) locale = navigator.language;\n @property({type: Array}) lines: number[][][] = [];\n @property({type: Array}) points: number[][] = [];\n @property() updateScale = (x: scaleLinear, y: scaleLinear, width: number, height: number): void => {};\n @property({type: Object}) margin = {top: 20, right: 20, bottom: 20, left: 40};\n @property({type: Object}) tickSize = {x: 100, y: 40};\n @property({type: Boolean}) pointerEvents = true;\n\n @state() pointer = {x: 0, y: 0};\n private resizeController = new ResizeController(this, {\n callback: () => [this.offsetWidth, this.offsetHeight],\n });\n\n private plotData: PlotPoint[] = [];\n private pointsData: PlotPoint[] = [];\n private scaleX = scaleLinear();\n private scaleY = scaleLinear();\n\n private bisectDistance = bisector((point: PlotPoint) => point.x);\n\n private line = line()\n .defined((point: PlotPoint) => !isNaN(point.y))\n .x((point: PlotPoint) => this.scaleX(point.x))\n .y((point: PlotPoint) => this.scaleY(point.y));\n private area = area()\n .defined((point: PlotPoint) => !isNaN(point.y))\n .x((point: PlotPoint) => this.scaleX(point.x))\n .y1((point: PlotPoint) => this.scaleY(point.y));\n private xAxis = axisBottom(this.scaleX).tickFormat((value: number) => this.tickFormat(value, 'x'));\n private yAxis = axisLeft(this.scaleY).tickFormat((value: number) => this.tickFormat(value, 'y'));\n private xGrid = axisBottom(this.scaleX).tickFormat(() => '');\n private yGrid = axisLeft(this.scaleY).tickFormat(() => '');\n\n private meterFormat: Intl.NumberFormat | null = null;\n private kilometerFormat: Intl.NumberFormat | null = null;\n\n override updated(changedProperties: PropertyValues) {\n if (changedProperties.has('locale')) {\n this.meterFormat = new Intl.NumberFormat(this.locale, {\n style: 'unit',\n unit: 'meter',\n });\n\n this.kilometerFormat = new Intl.NumberFormat(this.locale, {\n style: 'unit',\n unit: 'kilometer',\n });\n }\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n if (changedProperties.has('lines')) {\n this.plotData.length = 0;\n for (const line of this.lines) {\n const data = line.map((coordinate) => ({x: coordinate[3], y: coordinate[2], coordinate}));\n this.plotData.push(...simplify(data, this.tolerance));\n this.plotData.push({x: line[line.length - 1][3], y: NaN, coordinate: []});\n }\n\n this.scaleX.domain(extent(this.plotData, (data: PlotPoint) => data.x));\n this.scaleY.domain(extent(this.plotData, (data: PlotPoint) => data.y)).nice();\n\n this.updateScale(this.scaleX, this.scaleY, this.offsetWidth, this.offsetHeight);\n }\n if (changedProperties.has('points')) {\n this.pointsData.length = 0;\n for (const point of this.points) {\n this.pointsData.push({x: point[3], y: point[2], coordinate: point});\n }\n }\n }\n\n override render() {\n const [width, height] = this.resizeController.value ?? [0, 0];\n\n this.scaleX.range([this.margin.left, width - this.margin.right]);\n this.scaleY.range([height - this.margin.bottom, this.margin.top]);\n\n this.area.y0(height - this.margin.bottom);\n\n this.yGrid.tickSize(-width + this.margin.left + this.margin.right);\n this.xGrid.tickSize(height - this.margin.top - this.margin.bottom);\n\n const xTicks = width / this.tickSize.x;\n const yTicks = height / this.tickSize.y;\n this.xAxis.ticks(xTicks);\n this.xGrid.ticks(xTicks);\n this.yAxis.ticks(yTicks);\n this.yGrid.ticks(yTicks);\n\n select(this.querySelector('.axis.x')).call(this.xAxis);\n select(this.querySelector('.axis.y')).call(this.yAxis);\n select(this.querySelector('.grid.x')).call(this.xGrid);\n select(this.querySelector('.grid.y')).call(this.yGrid);\n\n const offset = this.yGrid.offset();\n\n return svg`\n <svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">\n <g class=\"grid y\" transform=\"translate(${this.margin.left}, 0)\" />\n <g class=\"grid x\" transform=\"translate(0, ${this.margin.bottom})\" />\n <g class=\"axis x\" transform=\"translate(0, ${height - this.margin.bottom})\" />\n <g class=\"axis y\" transform=\"translate(${this.margin.left}, 0)\" />\n\n ${guard([this.lines, width, height], () => svg`\n <path class=\"area\" d=\"${this.area(this.plotData)}\" />\n <path class=\"elevation\" d=\"${this.line(this.plotData)}\" fill=\"none\" />`\n )}\n\n <g style=\"visibility: ${this.pointer.x > 0 ? 'visible' : 'hidden'}\">\n <g clip-path=\"polygon(0 0, ${this.pointer.x - this.margin.left} 0, ${this.pointer.x - this.margin.left} 100%, 0 100%)\">\n ${guard([this.lines, width, height], () => svg`<path class=\"elevation highlight\" d=\"${this.line(this.plotData)}\" fill=\"none\" />`)}\n </g>\n <line\n class=\"pointer-line\"\n x1=\"${this.pointer.x}\"\n y1=\"${this.margin.top}\"\n x2=\"${this.pointer.x}\"\n y2=\"${height - this.margin.bottom}\"\n />\n <circle class=\"pointer-circle-outline\" cx=\"${this.pointer.x}\" cy=\"${this.pointer.y}\" r=\"16\"/>\n <circle class=\"pointer-circle\" cx=\"${this.pointer.x}\" cy=\"${this.pointer.y}\" r=\"6\"/>\n </g>\n\n ${this.pointsData.map((point, index) => this.pointSvg(this.scaleX(point.x), this.scaleY(point.y), index))}\n\n <rect\n width=\"${width}\"\n height=\"${height}\"\n fill=\"none\"\n pointer-events=\"${this.pointerEvents ? 'all' : 'none'}\"\n style=\"display: block; touch-action: none;\"\n @pointermove=\"${this.pointerMove}\"\n @pointerout=\"${this.pointerOut}\"\n />\n <g \n transform=\"translate(${this.margin.left},${height - this.margin.bottom + offset})\"\n class=\"axis\"\n style=\"visibility: ${this.lines.length ? 'visible' : 'hidden'}\">\n <line x2=\"${width - this.margin.left - this.margin.right}\"></line>\n </g>\n </svg>\n `;\n }\n\n public tickFormat(value: number, axis: 'x' | 'y') {\n if (axis === 'y' || value < 1000) {\n return this.meterFormat!.format(value);\n } else {\n return this.kilometerFormat!.format(value / 1000);\n }\n }\n\n public pointSvg(x: number, y: number, index: number): TemplateResult {\n return svg`<circle class=\"point\" cx=\"${x}\" cy=\"${y}\" r=\"10\"/>`;\n }\n\n override firstUpdated() {\n // FIXME: because the ref element are used before render is done, we need to force an update\n this.requestUpdate();\n }\n\n private pointerMove(event: PointerEvent) {\n const pointerDistance = this.scaleX.invert(pointer(event)[0]);\n const index = Math.min(this.bisectDistance.left(this.plotData, pointerDistance), this.plotData.length - 1);\n\n if (index < 0) {\n return;\n }\n // FIXME:\n // var d0 = this.plotData[index - 1]\n // var d1 = this.plotData[index];\n // // work out which date value is closest to the mouse\n // var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;\n\n const data = this.plotData[index];\n\n if (isNaN(data.y)) {\n return;\n }\n\n this.pointer = {\n x: this.scaleX(data.x),\n y: this.scaleY(data.y),\n };\n\n this.dispatchEvent(\n new CustomEvent<OverDetails>('over', {\n detail: {\n coordinate: this.plotData[index].coordinate,\n position: this.pointer\n }\n }),\n );\n }\n\n private pointerOut() {\n this.pointer = {\n x: 0,\n y: 0,\n };\n this.dispatchEvent(new CustomEvent('out'));\n }\n\n override createRenderRoot() {\n return this;\n }\n}\n\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'elevation-profile': ElevationProfile;\n }\n}\n"],"names":[],"version":3,"file":"elevation-profile.d.ts.map"}
@@ -0,0 +1,285 @@
1
+ import {svg as $agntW$svg, LitElement as $agntW$LitElement} from "lit";
2
+ import {property as $agntW$property, state as $agntW$state, customElement as $agntW$customElement} from "lit/decorators.js";
3
+ import {ResizeController as $agntW$ResizeController} from "@lit-labs/observers/resize-controller.js";
4
+ import {guard as $agntW$guard} from "lit/directives/guard.js";
5
+ import {bisector as $agntW$bisector, extent as $agntW$extent} from "d3-array";
6
+ import {scaleLinear as $agntW$scaleLinear} from "d3-scale";
7
+ import {line as $agntW$line, area as $agntW$area} from "d3-shape";
8
+ import {axisBottom as $agntW$axisBottom, axisLeft as $agntW$axisLeft} from "d3-axis";
9
+ import {select as $agntW$select, pointer as $agntW$pointer} from "d3-selection";
10
+ import $agntW$simplifyjs from "simplify-js";
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+ var $916babf1e6dc2c08$var$__decorate = undefined && undefined.__decorate || function(decorators, target, key, desc) {
23
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
24
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
25
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
26
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
27
+ };
28
+ let $916babf1e6dc2c08$var$ElevationProfile = class ElevationProfile extends (0, $agntW$LitElement) {
29
+ constructor(){
30
+ super(...arguments);
31
+ this.tolerance = 1;
32
+ this.locale = navigator.language;
33
+ this.lines = [];
34
+ this.points = [];
35
+ this.updateScale = (x, y, width, height)=>{};
36
+ this.margin = {
37
+ top: 20,
38
+ right: 20,
39
+ bottom: 20,
40
+ left: 40
41
+ };
42
+ this.tickSize = {
43
+ x: 100,
44
+ y: 40
45
+ };
46
+ this.pointerEvents = true;
47
+ this.pointer = {
48
+ x: 0,
49
+ y: 0
50
+ };
51
+ this.resizeController = new (0, $agntW$ResizeController)(this, {
52
+ callback: ()=>[
53
+ this.offsetWidth,
54
+ this.offsetHeight
55
+ ]
56
+ });
57
+ this.plotData = [];
58
+ this.pointsData = [];
59
+ this.scaleX = (0, $agntW$scaleLinear)();
60
+ this.scaleY = (0, $agntW$scaleLinear)();
61
+ this.bisectDistance = (0, $agntW$bisector)((point)=>point.x);
62
+ this.line = (0, $agntW$line)().defined((point)=>!isNaN(point.y)).x((point)=>this.scaleX(point.x)).y((point)=>this.scaleY(point.y));
63
+ this.area = (0, $agntW$area)().defined((point)=>!isNaN(point.y)).x((point)=>this.scaleX(point.x)).y1((point)=>this.scaleY(point.y));
64
+ this.xAxis = (0, $agntW$axisBottom)(this.scaleX).tickFormat((value)=>this.tickFormat(value, "x"));
65
+ this.yAxis = (0, $agntW$axisLeft)(this.scaleY).tickFormat((value)=>this.tickFormat(value, "y"));
66
+ this.xGrid = (0, $agntW$axisBottom)(this.scaleX).tickFormat(()=>"");
67
+ this.yGrid = (0, $agntW$axisLeft)(this.scaleY).tickFormat(()=>"");
68
+ this.meterFormat = null;
69
+ this.kilometerFormat = null;
70
+ }
71
+ updated(changedProperties) {
72
+ if (changedProperties.has("locale")) {
73
+ this.meterFormat = new Intl.NumberFormat(this.locale, {
74
+ style: "unit",
75
+ unit: "meter"
76
+ });
77
+ this.kilometerFormat = new Intl.NumberFormat(this.locale, {
78
+ style: "unit",
79
+ unit: "kilometer"
80
+ });
81
+ }
82
+ }
83
+ willUpdate(changedProperties) {
84
+ if (changedProperties.has("lines")) {
85
+ this.plotData.length = 0;
86
+ for (const line of this.lines){
87
+ const data = line.map((coordinate)=>({
88
+ x: coordinate[3],
89
+ y: coordinate[2],
90
+ coordinate: coordinate
91
+ }));
92
+ this.plotData.push(...(0, $agntW$simplifyjs)(data, this.tolerance));
93
+ this.plotData.push({
94
+ x: line[line.length - 1][3],
95
+ y: NaN,
96
+ coordinate: []
97
+ });
98
+ }
99
+ this.scaleX.domain((0, $agntW$extent)(this.plotData, (data)=>data.x));
100
+ this.scaleY.domain((0, $agntW$extent)(this.plotData, (data)=>data.y)).nice();
101
+ this.updateScale(this.scaleX, this.scaleY, this.offsetWidth, this.offsetHeight);
102
+ }
103
+ if (changedProperties.has("points")) {
104
+ this.pointsData.length = 0;
105
+ for (const point of this.points)this.pointsData.push({
106
+ x: point[3],
107
+ y: point[2],
108
+ coordinate: point
109
+ });
110
+ }
111
+ }
112
+ render() {
113
+ const [width, height] = this.resizeController.value ?? [
114
+ 0,
115
+ 0
116
+ ];
117
+ this.scaleX.range([
118
+ this.margin.left,
119
+ width - this.margin.right
120
+ ]);
121
+ this.scaleY.range([
122
+ height - this.margin.bottom,
123
+ this.margin.top
124
+ ]);
125
+ this.area.y0(height - this.margin.bottom);
126
+ this.yGrid.tickSize(-width + this.margin.left + this.margin.right);
127
+ this.xGrid.tickSize(height - this.margin.top - this.margin.bottom);
128
+ const xTicks = width / this.tickSize.x;
129
+ const yTicks = height / this.tickSize.y;
130
+ this.xAxis.ticks(xTicks);
131
+ this.xGrid.ticks(xTicks);
132
+ this.yAxis.ticks(yTicks);
133
+ this.yGrid.ticks(yTicks);
134
+ (0, $agntW$select)(this.querySelector(".axis.x")).call(this.xAxis);
135
+ (0, $agntW$select)(this.querySelector(".axis.y")).call(this.yAxis);
136
+ (0, $agntW$select)(this.querySelector(".grid.x")).call(this.xGrid);
137
+ (0, $agntW$select)(this.querySelector(".grid.y")).call(this.yGrid);
138
+ const offset = this.yGrid.offset();
139
+ return (0, $agntW$svg)`
140
+ <svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
141
+ <g class="grid y" transform="translate(${this.margin.left}, 0)" />
142
+ <g class="grid x" transform="translate(0, ${this.margin.bottom})" />
143
+ <g class="axis x" transform="translate(0, ${height - this.margin.bottom})" />
144
+ <g class="axis y" transform="translate(${this.margin.left}, 0)" />
145
+
146
+ ${(0, $agntW$guard)([
147
+ this.lines,
148
+ width,
149
+ height
150
+ ], ()=>(0, $agntW$svg)`
151
+ <path class="area" d="${this.area(this.plotData)}" />
152
+ <path class="elevation" d="${this.line(this.plotData)}" fill="none" />`)}
153
+
154
+ <g style="visibility: ${this.pointer.x > 0 ? "visible" : "hidden"}">
155
+ <g clip-path="polygon(0 0, ${this.pointer.x - this.margin.left} 0, ${this.pointer.x - this.margin.left} 100%, 0 100%)">
156
+ ${(0, $agntW$guard)([
157
+ this.lines,
158
+ width,
159
+ height
160
+ ], ()=>(0, $agntW$svg)`<path class="elevation highlight" d="${this.line(this.plotData)}" fill="none" />`)}
161
+ </g>
162
+ <line
163
+ class="pointer-line"
164
+ x1="${this.pointer.x}"
165
+ y1="${this.margin.top}"
166
+ x2="${this.pointer.x}"
167
+ y2="${height - this.margin.bottom}"
168
+ />
169
+ <circle class="pointer-circle-outline" cx="${this.pointer.x}" cy="${this.pointer.y}" r="16"/>
170
+ <circle class="pointer-circle" cx="${this.pointer.x}" cy="${this.pointer.y}" r="6"/>
171
+ </g>
172
+
173
+ ${this.pointsData.map((point, index)=>this.pointSvg(this.scaleX(point.x), this.scaleY(point.y), index))}
174
+
175
+ <rect
176
+ width="${width}"
177
+ height="${height}"
178
+ fill="none"
179
+ pointer-events="${this.pointerEvents ? "all" : "none"}"
180
+ style="display: block; touch-action: none;"
181
+ @pointermove="${this.pointerMove}"
182
+ @pointerout="${this.pointerOut}"
183
+ />
184
+ <g
185
+ transform="translate(${this.margin.left},${height - this.margin.bottom + offset})"
186
+ class="axis"
187
+ style="visibility: ${this.lines.length ? "visible" : "hidden"}">
188
+ <line x2="${width - this.margin.left - this.margin.right}"></line>
189
+ </g>
190
+ </svg>
191
+ `;
192
+ }
193
+ tickFormat(value, axis) {
194
+ if (axis === "y" || value < 1000) return this.meterFormat.format(value);
195
+ else return this.kilometerFormat.format(value / 1000);
196
+ }
197
+ pointSvg(x, y, index) {
198
+ return (0, $agntW$svg)`<circle class="point" cx="${x}" cy="${y}" r="10"/>`;
199
+ }
200
+ firstUpdated() {
201
+ // FIXME: because the ref element are used before render is done, we need to force an update
202
+ this.requestUpdate();
203
+ }
204
+ pointerMove(event) {
205
+ const pointerDistance = this.scaleX.invert((0, $agntW$pointer)(event)[0]);
206
+ const index = Math.min(this.bisectDistance.left(this.plotData, pointerDistance), this.plotData.length - 1);
207
+ if (index < 0) return;
208
+ // FIXME:
209
+ // var d0 = this.plotData[index - 1]
210
+ // var d1 = this.plotData[index];
211
+ // // work out which date value is closest to the mouse
212
+ // var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;
213
+ const data = this.plotData[index];
214
+ if (isNaN(data.y)) return;
215
+ this.pointer = {
216
+ x: this.scaleX(data.x),
217
+ y: this.scaleY(data.y)
218
+ };
219
+ this.dispatchEvent(new CustomEvent("over", {
220
+ detail: {
221
+ coordinate: this.plotData[index].coordinate,
222
+ position: this.pointer
223
+ }
224
+ }));
225
+ }
226
+ pointerOut() {
227
+ this.pointer = {
228
+ x: 0,
229
+ y: 0
230
+ };
231
+ this.dispatchEvent(new CustomEvent("out"));
232
+ }
233
+ createRenderRoot() {
234
+ return this;
235
+ }
236
+ };
237
+ $916babf1e6dc2c08$var$__decorate([
238
+ (0, $agntW$property)({
239
+ type: Number
240
+ })
241
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "tolerance", void 0);
242
+ $916babf1e6dc2c08$var$__decorate([
243
+ (0, $agntW$property)({
244
+ type: String
245
+ })
246
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "locale", void 0);
247
+ $916babf1e6dc2c08$var$__decorate([
248
+ (0, $agntW$property)({
249
+ type: Array
250
+ })
251
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "lines", void 0);
252
+ $916babf1e6dc2c08$var$__decorate([
253
+ (0, $agntW$property)({
254
+ type: Array
255
+ })
256
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "points", void 0);
257
+ $916babf1e6dc2c08$var$__decorate([
258
+ (0, $agntW$property)()
259
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "updateScale", void 0);
260
+ $916babf1e6dc2c08$var$__decorate([
261
+ (0, $agntW$property)({
262
+ type: Object
263
+ })
264
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "margin", void 0);
265
+ $916babf1e6dc2c08$var$__decorate([
266
+ (0, $agntW$property)({
267
+ type: Object
268
+ })
269
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "tickSize", void 0);
270
+ $916babf1e6dc2c08$var$__decorate([
271
+ (0, $agntW$property)({
272
+ type: Boolean
273
+ })
274
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "pointerEvents", void 0);
275
+ $916babf1e6dc2c08$var$__decorate([
276
+ (0, $agntW$state)()
277
+ ], $916babf1e6dc2c08$var$ElevationProfile.prototype, "pointer", void 0);
278
+ $916babf1e6dc2c08$var$ElevationProfile = $916babf1e6dc2c08$var$__decorate([
279
+ (0, $agntW$customElement)("elevation-profile")
280
+ ], $916babf1e6dc2c08$var$ElevationProfile);
281
+ var $916babf1e6dc2c08$export$2e2bcd8739ae039 = $916babf1e6dc2c08$var$ElevationProfile;
282
+
283
+
284
+ export {$916babf1e6dc2c08$export$2e2bcd8739ae039 as default};
285
+ //# sourceMappingURL=elevation-profile.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["elevation-profile.ts"],"sourcesContent":["import {LitElement, svg} from 'lit';\nimport {customElement, state, property} from 'lit/decorators.js';\nimport {ResizeController} from '@lit-labs/observers/resize-controller.js';\nimport {guard} from 'lit/directives/guard.js';\nimport type {PropertyValues, TemplateResult} from 'lit';\n\nimport {extent, bisector} from 'd3-array';\nimport {scaleLinear} from 'd3-scale';\nimport {line, area} from 'd3-shape';\nimport {axisBottom, axisLeft} from 'd3-axis';\nimport {select, pointer} from 'd3-selection';\n\nimport simplify from 'simplify-js';\n\ntype PlotPoint = {\n x: number;\n y: number;\n coordinate: number[];\n};\n\nexport type OverDetails = {\n coordinate: number[];\n position: {x: number; y: number};\n};\n\n@customElement('elevation-profile')\nexport default class ElevationProfile extends LitElement {\n @property({type: Number}) tolerance = 1;\n @property({type: String}) locale = navigator.language;\n @property({type: Array}) lines: number[][][] = [];\n @property({type: Array}) points: number[][] = [];\n @property() updateScale = (x: scaleLinear, y: scaleLinear, width: number, height: number): void => {};\n @property({type: Object}) margin = {top: 20, right: 20, bottom: 20, left: 40};\n @property({type: Object}) tickSize = {x: 100, y: 40};\n @property({type: Boolean}) pointerEvents = true;\n\n @state() pointer = {x: 0, y: 0};\n private resizeController = new ResizeController(this, {\n callback: () => [this.offsetWidth, this.offsetHeight],\n });\n\n private plotData: PlotPoint[] = [];\n private pointsData: PlotPoint[] = [];\n private scaleX = scaleLinear();\n private scaleY = scaleLinear();\n\n private bisectDistance = bisector((point: PlotPoint) => point.x);\n\n private line = line()\n .defined((point: PlotPoint) => !isNaN(point.y))\n .x((point: PlotPoint) => this.scaleX(point.x))\n .y((point: PlotPoint) => this.scaleY(point.y));\n private area = area()\n .defined((point: PlotPoint) => !isNaN(point.y))\n .x((point: PlotPoint) => this.scaleX(point.x))\n .y1((point: PlotPoint) => this.scaleY(point.y));\n private xAxis = axisBottom(this.scaleX).tickFormat((value: number) => this.tickFormat(value, 'x'));\n private yAxis = axisLeft(this.scaleY).tickFormat((value: number) => this.tickFormat(value, 'y'));\n private xGrid = axisBottom(this.scaleX).tickFormat(() => '');\n private yGrid = axisLeft(this.scaleY).tickFormat(() => '');\n\n private meterFormat: Intl.NumberFormat | null = null;\n private kilometerFormat: Intl.NumberFormat | null = null;\n\n override updated(changedProperties: PropertyValues) {\n if (changedProperties.has('locale')) {\n this.meterFormat = new Intl.NumberFormat(this.locale, {\n style: 'unit',\n unit: 'meter',\n });\n\n this.kilometerFormat = new Intl.NumberFormat(this.locale, {\n style: 'unit',\n unit: 'kilometer',\n });\n }\n }\n\n override willUpdate(changedProperties: PropertyValues) {\n if (changedProperties.has('lines')) {\n this.plotData.length = 0;\n for (const line of this.lines) {\n const data = line.map((coordinate) => ({x: coordinate[3], y: coordinate[2], coordinate}));\n this.plotData.push(...simplify(data, this.tolerance));\n this.plotData.push({x: line[line.length - 1][3], y: NaN, coordinate: []});\n }\n\n this.scaleX.domain(extent(this.plotData, (data: PlotPoint) => data.x));\n this.scaleY.domain(extent(this.plotData, (data: PlotPoint) => data.y)).nice();\n\n this.updateScale(this.scaleX, this.scaleY, this.offsetWidth, this.offsetHeight);\n }\n if (changedProperties.has('points')) {\n this.pointsData.length = 0;\n for (const point of this.points) {\n this.pointsData.push({x: point[3], y: point[2], coordinate: point});\n }\n }\n }\n\n override render() {\n const [width, height] = this.resizeController.value ?? [0, 0];\n\n this.scaleX.range([this.margin.left, width - this.margin.right]);\n this.scaleY.range([height - this.margin.bottom, this.margin.top]);\n\n this.area.y0(height - this.margin.bottom);\n\n this.yGrid.tickSize(-width + this.margin.left + this.margin.right);\n this.xGrid.tickSize(height - this.margin.top - this.margin.bottom);\n\n const xTicks = width / this.tickSize.x;\n const yTicks = height / this.tickSize.y;\n this.xAxis.ticks(xTicks);\n this.xGrid.ticks(xTicks);\n this.yAxis.ticks(yTicks);\n this.yGrid.ticks(yTicks);\n\n select(this.querySelector('.axis.x')).call(this.xAxis);\n select(this.querySelector('.axis.y')).call(this.yAxis);\n select(this.querySelector('.grid.x')).call(this.xGrid);\n select(this.querySelector('.grid.y')).call(this.yGrid);\n\n const offset = this.yGrid.offset();\n\n return svg`\n <svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">\n <g class=\"grid y\" transform=\"translate(${this.margin.left}, 0)\" />\n <g class=\"grid x\" transform=\"translate(0, ${this.margin.bottom})\" />\n <g class=\"axis x\" transform=\"translate(0, ${height - this.margin.bottom})\" />\n <g class=\"axis y\" transform=\"translate(${this.margin.left}, 0)\" />\n\n ${guard([this.lines, width, height], () => svg`\n <path class=\"area\" d=\"${this.area(this.plotData)}\" />\n <path class=\"elevation\" d=\"${this.line(this.plotData)}\" fill=\"none\" />`\n )}\n\n <g style=\"visibility: ${this.pointer.x > 0 ? 'visible' : 'hidden'}\">\n <g clip-path=\"polygon(0 0, ${this.pointer.x - this.margin.left} 0, ${this.pointer.x - this.margin.left} 100%, 0 100%)\">\n ${guard([this.lines, width, height], () => svg`<path class=\"elevation highlight\" d=\"${this.line(this.plotData)}\" fill=\"none\" />`)}\n </g>\n <line\n class=\"pointer-line\"\n x1=\"${this.pointer.x}\"\n y1=\"${this.margin.top}\"\n x2=\"${this.pointer.x}\"\n y2=\"${height - this.margin.bottom}\"\n />\n <circle class=\"pointer-circle-outline\" cx=\"${this.pointer.x}\" cy=\"${this.pointer.y}\" r=\"16\"/>\n <circle class=\"pointer-circle\" cx=\"${this.pointer.x}\" cy=\"${this.pointer.y}\" r=\"6\"/>\n </g>\n\n ${this.pointsData.map((point, index) => this.pointSvg(this.scaleX(point.x), this.scaleY(point.y), index))}\n\n <rect\n width=\"${width}\"\n height=\"${height}\"\n fill=\"none\"\n pointer-events=\"${this.pointerEvents ? 'all' : 'none'}\"\n style=\"display: block; touch-action: none;\"\n @pointermove=\"${this.pointerMove}\"\n @pointerout=\"${this.pointerOut}\"\n />\n <g \n transform=\"translate(${this.margin.left},${height - this.margin.bottom + offset})\"\n class=\"axis\"\n style=\"visibility: ${this.lines.length ? 'visible' : 'hidden'}\">\n <line x2=\"${width - this.margin.left - this.margin.right}\"></line>\n </g>\n </svg>\n `;\n }\n\n public tickFormat(value: number, axis: 'x' | 'y') {\n if (axis === 'y' || value < 1000) {\n return this.meterFormat!.format(value);\n } else {\n return this.kilometerFormat!.format(value / 1000);\n }\n }\n\n public pointSvg(x: number, y: number, index: number): TemplateResult {\n return svg`<circle class=\"point\" cx=\"${x}\" cy=\"${y}\" r=\"10\"/>`;\n }\n\n override firstUpdated() {\n // FIXME: because the ref element are used before render is done, we need to force an update\n this.requestUpdate();\n }\n\n private pointerMove(event: PointerEvent) {\n const pointerDistance = this.scaleX.invert(pointer(event)[0]);\n const index = Math.min(this.bisectDistance.left(this.plotData, pointerDistance), this.plotData.length - 1);\n\n if (index < 0) {\n return;\n }\n // FIXME:\n // var d0 = this.plotData[index - 1]\n // var d1 = this.plotData[index];\n // // work out which date value is closest to the mouse\n // var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;\n\n const data = this.plotData[index];\n\n if (isNaN(data.y)) {\n return;\n }\n\n this.pointer = {\n x: this.scaleX(data.x),\n y: this.scaleY(data.y),\n };\n\n this.dispatchEvent(\n new CustomEvent<OverDetails>('over', {\n detail: {\n coordinate: this.plotData[index].coordinate,\n position: this.pointer\n }\n }),\n );\n }\n\n private pointerOut() {\n this.pointer = {\n x: 0,\n y: 0,\n };\n this.dispatchEvent(new CustomEvent('out'));\n }\n\n override createRenderRoot() {\n return this;\n }\n}\n\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'elevation-profile': ElevationProfile;\n }\n}\n"],"names":[],"version":3,"file":"elevation-profile.js.map"}
@@ -62,8 +62,6 @@ export default class ElevationProfile extends LitElement {
62
62
  private meterFormat: Intl.NumberFormat | null = null;
63
63
  private kilometerFormat: Intl.NumberFormat | null = null;
64
64
 
65
- private lowestY: number | undefined;
66
-
67
65
  override updated(changedProperties: PropertyValues) {
68
66
  if (changedProperties.has('locale')) {
69
67
  this.meterFormat = new Intl.NumberFormat(this.locale, {
@@ -86,8 +84,6 @@ export default class ElevationProfile extends LitElement {
86
84
  this.plotData.push(...simplify(data, this.tolerance));
87
85
  this.plotData.push({x: line[line.length - 1][3], y: NaN, coordinate: []});
88
86
  }
89
- this.lowestY = this.plotData.length && this.plotData
90
- .reduce((a, b) => !isNaN(b.y) ? Math.min(a, b.y) : a, this.plotData[0].y);
91
87
 
92
88
  this.scaleX.domain(extent(this.plotData, (data: PlotPoint) => data.x));
93
89
  this.scaleY.domain(extent(this.plotData, (data: PlotPoint) => data.y)).nice();
@@ -125,8 +121,7 @@ export default class ElevationProfile extends LitElement {
125
121
  select(this.querySelector('.grid.x')).call(this.xGrid);
126
122
  select(this.querySelector('.grid.y')).call(this.yGrid);
127
123
 
128
-
129
- const firstYTick = this.scaleY.ticks(yTicks)[0];
124
+ const offset = this.yGrid.offset();
130
125
 
131
126
  return svg`
132
127
  <svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
@@ -167,9 +162,9 @@ export default class ElevationProfile extends LitElement {
167
162
  @pointerout="${this.pointerOut}"
168
163
  />
169
164
  <g
170
- transform="translate(${this.margin.left},${height - this.margin.bottom})"
165
+ transform="translate(${this.margin.left},${height - this.margin.bottom + offset})"
171
166
  class="axis"
172
- style="visibility: ${this.lowestY && firstYTick >= this.lowestY ? 'visible' : 'hidden'}">
167
+ style="visibility: ${this.lines.length ? 'visible' : 'hidden'}">
173
168
  <line x2="${width - this.margin.left - this.margin.right}"></line>
174
169
  </g>
175
170
  </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geoblocks/elevation-profile",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "license": "BSD-3-Clause",
5
5
  "repository": "github:geoblocks/elevation-profile",
6
6
  "type": "module",