]>
git.argeo.org Git - gpl/argeo-suite.git/blob - js/src/geo/OpenLayersMapPart.js
1 /** OpenLayers-based implementation.
2 * @module OpenLayersMapPart
5 import Map
from 'ol/Map.js';
6 import View
from 'ol/View.js';
7 import { fromLonLat
, getPointResolution
} from 'ol/proj.js';
8 import VectorSource
from 'ol/source/Vector.js';
9 import Feature
from 'ol/Feature.js';
10 import { Point
} from 'ol/geom.js';
11 import VectorLayer
from 'ol/layer/Vector.js';
12 import GeoJSON
from 'ol/format/GeoJSON.js';
13 import GPX
from 'ol/format/GPX.js';
14 import Select
from 'ol/interaction/Select.js';
15 import Overlay
from 'ol/Overlay.js';
16 import { Style
, Icon
} from 'ol/style.js';
18 import * as SLDReader
from '@nieuwlandgeo/sldreader';
20 import MapPart
from './MapPart.js';
22 /** OpenLayers implementation of MapPart. */
23 export default class OpenLayersMapPart
extends MapPart
{
24 /** The OpenLayers Map. */
27 /** Styled layer descriptor */
30 /** Externally added callback functions. */
33 /** Constructor taking the mapName as an argument. */
34 constructor(mapName
) {
40 // projection: 'EPSG:4326',
44 target
: this.getMapName(),
46 //this.#map.getView().set('projection', 'EPSG:4326', true);
49 /* GEOGRAPHICAL METHODS */
52 this.#map
.getView().setZoom(zoom
);
56 this.#map
.getView().setCenter(fromLonLat([lon
, lat
]));
59 addPoint(lng
, lat
, style
) {
60 let vectorSource
= new VectorSource({
61 features
: [new Feature({
62 geometry
: new Point(fromLonLat([lng
, lat
]))
65 this.#map
.addLayer(new VectorLayer({
71 addUrlLayer(url
, format
, style
, sld
) {
73 if (format
=== 'GEOJSON') {
74 featureFormat
= new GeoJSON();
76 else if (format
=== 'GPX') {
77 featureFormat
= new GPX();
79 throw new Error("Unsupported format " + format
);
81 const vectorSource
= new VectorSource({
83 format
: featureFormat
,
85 const vectorLayer
= new VectorLayer({
89 this.#applySLD(vectorLayer
, style
);
90 } else if (style
!== null) {
91 vectorLayer
.setStyle(style
);
93 this.#map
.addLayer(vectorLayer
);
97 const func
= new Function(js
);
98 const layer
= (func
)();
99 this.#map
.addLayer(layer
);
106 getLayerByName(name
) {
107 let layers
= this.#map
.getLayers();
108 for (let i
= 0; i
< layers
.getLength(); i
++) {
109 let layer
= layers
.item(i
);
110 let n
= layer
.get('name');
111 if (n
!== undefined) {
120 enableFeatureSingleClick() {
121 // we cannot use 'this' in the function provided to OpenLayers
123 this.#map
.on('singleclick', function(e
) {
125 // we chose the first one
126 e
.map
.forEachFeatureAtPixel(e
.pixel
, function(f
) {
130 if (feature
!== null)
131 mapPart
.callbacks
['onFeatureSingleClick'](feature
.get('path'));
135 enableFeatureSelected() {
136 // we cannot use 'this' in the function provided to OpenLayers
138 var select
= new Select();
139 this.#map
.addInteraction(select
);
140 select
.on('select', function(e
) {
141 if (e
.selected
.length
> 0) {
142 let feature
= e
.selected
[0];
143 mapPart
.callbacks
['onFeatureSelected'](feature
.get('path'));
148 enableFeaturePopup() {
149 // we cannot use 'this' in the function provided to OpenLayers
152 * Elements that make up the popup.
154 const container
= document
.getElementById('popup');
155 const content
= document
.getElementById('popup-content');
156 const closer
= document
.getElementById('popup-closer');
159 * Create an overlay to anchor the popup to the map.
161 const overlay
= new Overlay({
168 this.#map
.addOverlay(overlay
);
171 this.#map
.on('pointermove', function(e
) {
172 if (selected
!== null) {
173 selected
.setStyle(undefined);
177 e
.map
.forEachFeatureAtPixel(e
.pixel
, function(f
) {
182 if (selected
== null) {
183 overlay
.setPosition(undefined);
186 const coordinate
= e
.coordinate
;
187 const path
= selected
.get('path');
190 const res
= mapPart
.callbacks
['onFeaturePopup'](path
);
192 content
.innerHTML
= res
;
193 overlay
.setPosition(coordinate
);
195 overlay
.setPosition(undefined);
203 getMapDivCssClass() {
208 // STATIC FOR EXTENSION
210 static newStyle(args
) {
211 return new Style(args
);
214 static newIcon(args
) {
215 return new Icon(args
);
223 this.#sld
= SLDReader
.Reader(xml
);
226 /** Get a FeatureTypeStyle (https://nieuwlandgeo.github.io/SLDReader/api.html#FeatureTypeStyle). */
227 getFeatureTypeStyle(styledLayerName, styleName) {
228 const sldLayer = SLDReader.getLayer(this.#sld, styledLayerName);
229 const style = styleName === undefined ? SLDReader.getStyle(sldLayer) : SLDReader.getStyle(sldLayer, styleName);
230 // OpenLayers can only use one definition
231 const featureTypeStyle = style.featuretypestyles[0];
232 return featureTypeStyle;
235 applyStyle(layerName, styledLayerName, styleName) {
236 const layer = this.getLayerByName(layerName);
237 const featureTypeStyle = this.getFeatureTypeStyle(styledLayerName, styleName);
238 const viewProjection = this.#map.getView().getProjection();
239 const olStyleFunction = SLDReader.createOlStyleFunction(featureTypeStyle, {
240 // Use the convertResolution option to calculate a more accurate resolution.
241 convertResolution: viewResolution => {
242 const viewCenter = this.#map.getView().getCenter();
243 return getPointResolution(viewProjection, viewResolution, viewCenter);
245 // If you use point icons with an ExternalGraphic, you have to use imageLoadCallback
246 // to update the vector layer when an image finishes loading.
247 // If you do not do this, the image will only be visible after next layer pan/zoom.
248 imageLoadedCallback: () => {
252 layer.setStyle(olStyleFunction);
255 #applySLD(vectorLayer, text) {
256 const sldObject = SLDReader.Reader(text);
257 const sldLayer = SLDReader.getLayer(sldObject);
258 const style = SLDReader.getStyle(sldLayer);
259 const featureTypeStyle = style.featuretypestyles[0];
261 const viewProjection = this.#map.getView().getProjection();
262 const olStyleFunction = SLDReader.createOlStyleFunction(featureTypeStyle, {
263 // Use the convertResolution option to calculate a more accurate resolution.
264 convertResolution: viewResolution => {
265 const viewCenter = this.#map.getView().getCenter();
266 return getPointResolution(viewProjection, viewResolution, viewCenter);
268 // If you use point icons with an ExternalGraphic, you have to use imageLoadCallback
269 // to update the vector layer when an image finishes loading.
270 // If you do not do this, the image will only be visible after next layer pan/zoom.
271 imageLoadedCallback: () => {
272 vectorLayer.changed();
275 vectorLayer.setStyle(olStyleFunction);