Mercurial > gemma
comparison client/src/components/map/layers.js @ 3011:fc8fbea24568
client: moved map component, layer factory and styles to own subdirectory
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Thu, 11 Apr 2019 12:14:01 +0200 |
parents | |
children | 2e2a271c1026 |
comparison
equal
deleted
inserted
replaced
3010:293bdd05ffcd | 3011:fc8fbea24568 |
---|---|
1 import TileWMS from "ol/source/TileWMS"; | |
2 import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer"; | |
3 import OSM from "ol/source/OSM"; | |
4 import { Icon, Stroke, Style } from "ol/style"; | |
5 import VectorSource from "ol/source/Vector"; | |
6 import Point from "ol/geom/Point"; | |
7 import { bbox as bboxStrategy } from "ol/loadingstrategy"; | |
8 import { WFS, GeoJSON } from "ol/format"; | |
9 import { equalTo } from "ol/format/filter"; | |
10 import { HTTP } from "@/lib/http"; | |
11 import styles from "./styles"; | |
12 | |
13 const buildVectorLoader = ( | |
14 featureRequestOptions, | |
15 vectorSource, | |
16 bboxStrategyDisabled, | |
17 featurePostProcessor | |
18 ) => { | |
19 // build a function to be used for VectorSource.setLoader() | |
20 // make use of WFS().writeGetFeature to build the request | |
21 // and use our HTTP library to actually do it | |
22 // NOTE: the geometryName has to be given in featureRequestOptions if | |
23 // bboxStrategy (default) is used | |
24 featureRequestOptions.featureNS = "gemma"; | |
25 featureRequestOptions.featurePrefix = "gemma"; | |
26 featureRequestOptions.outputFormat = "application/json"; | |
27 return (extent, resolution, projection) => { | |
28 if (!bboxStrategyDisabled) { | |
29 featureRequestOptions.bbox = extent; | |
30 } | |
31 featureRequestOptions.srsName = projection.getCode(); | |
32 HTTP.post( | |
33 "/internal/wfs", | |
34 new XMLSerializer().serializeToString( | |
35 new WFS().writeGetFeature(featureRequestOptions) | |
36 ), | |
37 { | |
38 headers: { | |
39 "X-Gemma-Auth": localStorage.getItem("token"), | |
40 "Content-type": "text/xml; charset=UTF-8" | |
41 } | |
42 } | |
43 ) | |
44 .then(response => { | |
45 const features = new GeoJSON().readFeatures( | |
46 JSON.stringify(response.data) | |
47 ); | |
48 if (featurePostProcessor) { | |
49 features.map(f => featurePostProcessor(f)); | |
50 } | |
51 vectorSource.addFeatures(features); | |
52 }) | |
53 .catch(() => { | |
54 vectorSource.removeLoadedExtent(extent); | |
55 }); | |
56 }; | |
57 }; | |
58 | |
59 export default (function() { | |
60 return { | |
61 get(id) { | |
62 return this.config.find(l => l.get("id") === id); | |
63 }, | |
64 config: [ | |
65 new TileLayer({ | |
66 id: "OPENSTREETMAP", | |
67 label: "Open Streetmap", | |
68 visible: true, | |
69 source: new OSM() | |
70 }), | |
71 new TileLayer({ | |
72 id: "INLANDECDIS", | |
73 label: "Inland ECDIS chart Danube", | |
74 visible: true, | |
75 source: new TileWMS({ | |
76 preload: 1, | |
77 url: "https://service.d4d-portal.info/wms/", | |
78 crossOrigin: "anonymous", | |
79 params: { LAYERS: "d4d", VERSION: "1.1.1", TILED: true } | |
80 }) | |
81 }), | |
82 (function() { | |
83 const source = new VectorSource({ strategy: bboxStrategy }); | |
84 source.setLoader( | |
85 buildVectorLoader( | |
86 { | |
87 featureTypes: ["waterway_area"], | |
88 geometryName: "area" | |
89 }, | |
90 source | |
91 ) | |
92 ); | |
93 return new VectorLayer({ | |
94 id: "WATERWAYAREA", | |
95 label: "Waterway Area", | |
96 visible: true, | |
97 style: new Style({ | |
98 stroke: new Stroke({ | |
99 color: "rgba(0, 102, 0, 1)", | |
100 width: 2 | |
101 }) | |
102 }), | |
103 source | |
104 }); | |
105 })(), | |
106 (function() { | |
107 const source = new VectorSource({ strategy: bboxStrategy }); | |
108 source.setLoader( | |
109 buildVectorLoader( | |
110 { | |
111 featureTypes: ["stretches_geoserver"], | |
112 geometryName: "area" | |
113 }, | |
114 source, | |
115 f => { | |
116 if (f.getId() === this.selectedStretchId) { | |
117 f.set("highlighted", true); | |
118 } | |
119 return f; | |
120 } | |
121 ) | |
122 ); | |
123 return new VectorLayer({ | |
124 id: "STRETCHES", | |
125 label: "Stretches", | |
126 visible: false, | |
127 style: styles.stretches, | |
128 source | |
129 }); | |
130 })(), | |
131 (function() { | |
132 const source = new VectorSource(); | |
133 source.setLoader( | |
134 buildVectorLoader( | |
135 { | |
136 featureTypes: ["fairway_dimensions"], | |
137 filter: equalTo("level_of_service", 1) | |
138 }, | |
139 source, | |
140 true | |
141 ) | |
142 ); | |
143 return new VectorLayer({ | |
144 id: "FAIRWAYDIMENSIONSLOS1", | |
145 label: "LOS 1 Fairway Dimensions", | |
146 visible: false, | |
147 style: styles.fwd1, | |
148 source | |
149 }); | |
150 })(), | |
151 (function() { | |
152 const source = new VectorSource(); | |
153 source.setLoader( | |
154 buildVectorLoader( | |
155 { | |
156 featureTypes: ["fairway_dimensions"], | |
157 filter: equalTo("level_of_service", 2) | |
158 }, | |
159 source, | |
160 true | |
161 ) | |
162 ); | |
163 return new VectorLayer({ | |
164 id: "FAIRWAYDIMENSIONSLOS2", | |
165 label: "LOS 2 Fairway Dimensions", | |
166 visible: false, | |
167 style: styles.fwd2, | |
168 source | |
169 }); | |
170 })(), | |
171 (function() { | |
172 const source = new VectorSource(); | |
173 source.setLoader( | |
174 buildVectorLoader( | |
175 { | |
176 featureTypes: ["fairway_dimensions"], | |
177 filter: equalTo("level_of_service", 3) | |
178 }, | |
179 source, | |
180 true | |
181 ) | |
182 ); | |
183 return new VectorLayer({ | |
184 id: "FAIRWAYDIMENSIONSLOS3", | |
185 label: "LOS 3 Fairway Dimensions", | |
186 visible: true, | |
187 style: styles.fwd3, | |
188 source | |
189 }); | |
190 })(), | |
191 (function() { | |
192 const source = new VectorSource({ strategy: bboxStrategy }); | |
193 source.setLoader( | |
194 buildVectorLoader( | |
195 { | |
196 featureTypes: ["waterway_axis"], | |
197 geometryName: "wtwaxs" | |
198 }, | |
199 source | |
200 ) | |
201 ); | |
202 return new VectorLayer({ | |
203 id: "WATERWAYAXIS", | |
204 label: "Waterway Axis", | |
205 visible: true, | |
206 style: new Style({ | |
207 stroke: new Stroke({ | |
208 color: "rgba(0, 0, 255, .5)", | |
209 lineDash: [5, 5], | |
210 width: 2 | |
211 }) | |
212 }), | |
213 // TODO: Set layer in layertree active/inactive depending on | |
214 // resolution. | |
215 maxResolution: 5, | |
216 minResolution: 0, | |
217 source | |
218 }); | |
219 })(), | |
220 (function() { | |
221 const source = new VectorSource({ strategy: bboxStrategy }); | |
222 source.setLoader( | |
223 buildVectorLoader( | |
224 { | |
225 featureTypes: ["waterway_profiles"], | |
226 geometryName: "geom" | |
227 }, | |
228 source | |
229 ) | |
230 ); | |
231 return new VectorLayer({ | |
232 id: "WATERWAYPROFILES", | |
233 label: "Waterway Profiles", | |
234 visible: true, | |
235 style: new Style({ | |
236 stroke: new Stroke({ | |
237 color: "rgba(0, 0, 255, .5)", | |
238 lineDash: [5, 5], | |
239 width: 2 | |
240 }) | |
241 }), | |
242 maxResolution: 2.5, | |
243 minResolution: 0, | |
244 source | |
245 }); | |
246 })(), | |
247 (function() { | |
248 const source = new VectorSource({ strategy: bboxStrategy }); | |
249 source.setLoader( | |
250 buildVectorLoader( | |
251 { | |
252 featureTypes: ["bottlenecks_geoserver"], | |
253 geometryName: "area" | |
254 }, | |
255 source | |
256 ) | |
257 ); | |
258 return new VectorLayer({ | |
259 id: "BOTTLENECKS", | |
260 label: "Bottlenecks", | |
261 visible: true, | |
262 style: styles.bottleneck, | |
263 source | |
264 }); | |
265 })(), | |
266 new TileLayer({ | |
267 id: "BOTTLENECKISOLINE", | |
268 label: "Bottleneck isolines", | |
269 visible: false, | |
270 source: new TileWMS({ | |
271 preload: 0, | |
272 projection: "EPSG:3857", | |
273 url: window.location.origin + "/api/internal/wms", | |
274 params: { | |
275 LAYERS: "sounding_results_contour_lines_geoserver", | |
276 VERSION: "1.1.1", | |
277 TILED: true | |
278 }, | |
279 tileLoadFunction: function(tile, src) { | |
280 // console.log("calling for", tile, src); | |
281 HTTP.get(src, { | |
282 headers: { | |
283 "X-Gemma-Auth": localStorage.getItem("token") | |
284 }, | |
285 responseType: "blob" | |
286 }).then(response => { | |
287 tile.getImage().src = URL.createObjectURL(response.data); | |
288 }); | |
289 } // TODO tile.setState(TileState.ERROR); | |
290 }) | |
291 }), | |
292 new TileLayer({ | |
293 id: "DIFFERENCES", | |
294 label: "Bottleneck Differences", | |
295 visible: false, | |
296 source: new TileWMS({ | |
297 preload: 0, | |
298 projection: "EPSG:4326", | |
299 url: window.location.origin + "/api/internal/wms", | |
300 params: { | |
301 LAYERS: "sounding_differences", | |
302 VERSION: "1.1.1", | |
303 TILED: true | |
304 }, | |
305 tileLoadFunction: function(tile, src) { | |
306 // console.log("calling for", tile, src); | |
307 HTTP.get(src, { | |
308 headers: { | |
309 "X-Gemma-Auth": localStorage.getItem("token") | |
310 }, | |
311 responseType: "blob" | |
312 }).then(response => { | |
313 tile.getImage().src = URL.createObjectURL(response.data); | |
314 }); | |
315 } // TODO tile.setState(TileState.ERROR); | |
316 }) | |
317 }), | |
318 (function() { | |
319 const source = new VectorSource({ strategy: bboxStrategy }); | |
320 source.setLoader( | |
321 buildVectorLoader( | |
322 { | |
323 featureTypes: ["bottlenecks_geoserver"], | |
324 geometryName: "area" | |
325 }, | |
326 source | |
327 ) | |
328 ); | |
329 return new VectorLayer({ | |
330 id: "BOTTLENECKSTATUS", | |
331 label: "Critical Bottlenecks", | |
332 forLegendStyle: { point: true, resolution: 16 }, | |
333 visible: true, | |
334 style: styles.bottleneckStatus, | |
335 source | |
336 }); | |
337 })(), | |
338 (function() { | |
339 const source = new VectorSource({ strategy: bboxStrategy }); | |
340 source.setLoader( | |
341 buildVectorLoader( | |
342 { | |
343 featureTypes: ["distance_marks_ashore_geoserver"], | |
344 geometryName: "geom" | |
345 }, | |
346 source | |
347 ) | |
348 ); | |
349 return new VectorLayer({ | |
350 id: "DISTANCEMARKS", | |
351 label: "Distance marks", | |
352 forLegendStyle: { point: true, resolution: 8 }, | |
353 visible: false, | |
354 source | |
355 }); | |
356 })(), | |
357 (function() { | |
358 const source = new VectorSource({ strategy: bboxStrategy }); | |
359 source.setLoader( | |
360 buildVectorLoader( | |
361 { | |
362 featureTypes: ["distance_marks_geoserver"], | |
363 geometryName: "geom" | |
364 }, | |
365 source | |
366 ) | |
367 ); | |
368 return new VectorLayer({ | |
369 id: "DISTANCEMARKSAXIS", | |
370 label: "Distance marks, Axis", | |
371 forLegendStyle: { point: true, resolution: 8 }, | |
372 visible: true, | |
373 style: styles.dma, | |
374 source | |
375 }); | |
376 })(), | |
377 (function() { | |
378 const source = new VectorSource({ strategy: bboxStrategy }); | |
379 source.setLoader( | |
380 buildVectorLoader( | |
381 { | |
382 featureTypes: ["gauges_geoserver"], | |
383 geometryName: "geom" | |
384 }, | |
385 source | |
386 ) | |
387 ); | |
388 return new VectorLayer({ | |
389 id: "GAUGES", | |
390 label: "Gauges", | |
391 forLegendStyle: { point: true, resolution: 8 }, | |
392 visible: true, | |
393 style: styles.gauge, | |
394 maxResolution: 100, | |
395 minResolution: 0, | |
396 source | |
397 }); | |
398 })(), | |
399 new VectorLayer({ | |
400 id: "DRAWTOOL", | |
401 label: "Draw Tool", | |
402 visible: true, | |
403 source: new VectorSource({ wrapX: false }), | |
404 style: function(feature) { | |
405 // adapted from OpenLayer's LineString Arrow Example | |
406 var geometry = feature.getGeometry(); | |
407 var styles = [ | |
408 // linestring | |
409 new Style({ | |
410 stroke: new Stroke({ | |
411 color: "#369aca", | |
412 width: 2 | |
413 }) | |
414 }) | |
415 ]; | |
416 | |
417 if (geometry.getType() === "LineString") { | |
418 geometry.forEachSegment(function(start, end) { | |
419 var dx = end[0] - start[0]; | |
420 var dy = end[1] - start[1]; | |
421 var rotation = Math.atan2(dy, dx); | |
422 // arrows | |
423 styles.push( | |
424 new Style({ | |
425 geometry: new Point(end), | |
426 image: new Icon({ | |
427 // we need to make sure the image is loaded by Vue Loader | |
428 src: require("@/assets/linestring_arrow.png"), | |
429 // fiddling with the anchor's y value does not help to | |
430 // position the image more centered on the line ending, as the | |
431 // default line style seems to be slightly uncentered in the | |
432 // anti-aliasing, but the image is not placed with subpixel | |
433 // precision | |
434 anchor: [0.75, 0.5], | |
435 rotateWithView: true, | |
436 rotation: -rotation | |
437 }) | |
438 }) | |
439 ); | |
440 }); | |
441 } | |
442 return styles; | |
443 } | |
444 }), | |
445 new VectorLayer({ | |
446 id: "CUTTOOL", | |
447 label: "Cut Tool", | |
448 visible: true, | |
449 source: new VectorSource({ wrapX: false }), | |
450 style: function(feature) { | |
451 // adapted from OpenLayer's LineString Arrow Example | |
452 var geometry = feature.getGeometry(); | |
453 var styles = [ | |
454 // linestring | |
455 new Style({ | |
456 stroke: new Stroke({ | |
457 color: "#333333", | |
458 width: 2, | |
459 lineDash: [7, 7] | |
460 }) | |
461 }) | |
462 ]; | |
463 | |
464 if (geometry.getType() === "LineString") { | |
465 geometry.forEachSegment(function(start, end) { | |
466 var dx = end[0] - start[0]; | |
467 var dy = end[1] - start[1]; | |
468 var rotation = Math.atan2(dy, dx); | |
469 // arrows | |
470 styles.push( | |
471 new Style({ | |
472 geometry: new Point(end), | |
473 image: new Icon({ | |
474 // we need to make sure the image is loaded by Vue Loader | |
475 src: require("@/assets/linestring_arrow_grey.png"), | |
476 // fiddling with the anchor's y value does not help to | |
477 // position the image more centered on the line ending, as the | |
478 // default line style seems to be slightly uncentered in the | |
479 // anti-aliasing, but the image is not placed with subpixel | |
480 // precision | |
481 anchor: [0.75, 0.5], | |
482 rotateWithView: true, | |
483 rotation: -rotation | |
484 }) | |
485 }) | |
486 ); | |
487 }); | |
488 } | |
489 return styles; | |
490 } | |
491 }) | |
492 ] | |
493 }; | |
494 })(); |