1
|
|
|
import Map from 'ol/Map'; |
2
|
|
|
import View from 'ol/View' |
3
|
|
|
import TileLayer from 'ol/layer/Tile'; |
4
|
|
|
import OSM from 'ol/source/OSM'; |
5
|
|
|
import SourceStamen from 'ol/source/Stamen'; |
6
|
|
|
import LayerGroup from "ol/layer/Group"; |
7
|
|
|
import LayerSwitcher from "ol-layerswitcher"; |
8
|
|
|
import {fromLonLat, transform} from "ol/proj"; |
9
|
|
|
import VectorLayer from "ol/layer/Vector"; |
10
|
|
|
import VectorSource from "ol/source/Vector"; |
11
|
|
|
import {Feature, Overlay} from "ol"; |
12
|
|
|
import ScaleLine from 'ol/control/ScaleLine'; |
13
|
|
|
import {Point} from "ol/geom"; |
14
|
|
|
import {Fill, Icon, Stroke, Style, Text} from "ol/style"; |
15
|
|
|
import {GPX, KML} from "ol/format"; |
16
|
|
|
import {MousePosition} from "ol/control"; |
17
|
|
|
import {createStringXY, format} from "ol/coordinate"; |
18
|
|
|
import CircleStyle from "ol/style/Circle"; |
19
|
|
|
|
20
|
|
|
const mapOpts = olMapData[0].mapOpts; |
|
|
|
|
21
|
|
|
const poi = olMapData[0].poi; |
22
|
|
|
|
23
|
|
|
const overlayGroup = new LayerGroup({ |
24
|
|
|
title: 'Overlays', |
25
|
|
|
layers: [] |
26
|
|
|
}) |
27
|
|
|
const map = new Map({ |
28
|
|
|
target: document.getElementById('map'), |
29
|
|
|
layers: [ |
30
|
|
|
new LayerGroup({ |
31
|
|
|
'title': 'Base maps', |
32
|
|
|
layers: [ |
33
|
|
|
new LayerGroup({ |
34
|
|
|
title: 'Water color with labels', |
35
|
|
|
type: 'base', |
36
|
|
|
combine: true, |
37
|
|
|
visible: false, |
38
|
|
|
layers: [ |
39
|
|
|
new TileLayer({source: new SourceStamen({layer: 'watercolor'})}), |
40
|
|
|
new TileLayer({source: new SourceStamen({layer: 'terrain-labels'})}) |
41
|
|
|
] |
42
|
|
|
}), |
43
|
|
|
new TileLayer({ |
44
|
|
|
title: 'Water color', |
45
|
|
|
type: 'base', |
46
|
|
|
visible: false, |
47
|
|
|
source: new SourceStamen({layer: 'watercolor'}) |
48
|
|
|
}), |
49
|
|
|
new TileLayer({ |
50
|
|
|
title: 'OSM', |
51
|
|
|
type: 'base', |
52
|
|
|
visible: true, |
53
|
|
|
source: new OSM() |
54
|
|
|
}) |
55
|
|
|
] |
56
|
|
|
}) |
57
|
|
|
, overlayGroup |
58
|
|
|
], |
59
|
|
|
|
60
|
|
|
view: new View({ |
61
|
|
|
center: transform([mapOpts.lon, mapOpts.lat], 'EPSG:4326', 'EPSG:3857'), |
62
|
|
|
zoom: mapOpts.zoom, |
63
|
|
|
projection: 'EPSG:3857' |
64
|
|
|
}) |
65
|
|
|
}); |
66
|
|
|
|
67
|
|
|
|
68
|
|
|
const layerSwitcher = new LayerSwitcher(); |
69
|
|
|
map.addControl(layerSwitcher); |
70
|
|
|
map.addControl(new ScaleLine({bar: true, text: true})); |
71
|
|
|
map.addControl(new MousePosition({ |
72
|
|
|
coordinateFormat: createStringXY(4), |
73
|
|
|
projection: 'EPSG:4326', |
74
|
|
|
// coordinateFormat: createStringXY(0), |
75
|
|
|
// projection: 'EPSG:3857' |
76
|
|
|
})); |
77
|
|
|
|
78
|
|
|
|
79
|
|
|
const vectorSource = new VectorSource(); |
80
|
|
|
const vectorLayer = new VectorLayer({ |
81
|
|
|
source: vectorSource, |
82
|
|
|
title: 'POI', |
83
|
|
|
visible: true, |
84
|
|
|
}); |
85
|
|
|
// map.addLayer(vectorLayer); |
86
|
|
|
overlayGroup.getLayers().push(vectorLayer); |
87
|
|
|
|
88
|
|
|
|
89
|
|
|
const iconScale = 2; |
90
|
|
|
|
91
|
|
|
poi.forEach((p) => { |
92
|
|
|
console.debug(p); |
93
|
|
|
const f = new Feature({ |
94
|
|
|
geometry: new Point(fromLonLat([p.lon, p.lat])), |
95
|
|
|
description: p.txt, |
96
|
|
|
img: p.img, |
97
|
|
|
rowId: p.rowId, |
98
|
|
|
lat: p.lat, |
99
|
|
|
lon: p.lon, |
100
|
|
|
angle: p.angle, |
101
|
|
|
alt: p.img.substring(0, p.img.lastIndexOf(".")) |
102
|
|
|
|
103
|
|
|
}); |
104
|
|
|
|
105
|
|
|
f.setId(p.rowId); |
106
|
|
|
f.setStyle(new Style({ |
107
|
|
|
text: new Text({ |
108
|
|
|
text: "" + p.rowId, |
109
|
|
|
textAlign: 'left', |
110
|
|
|
textBaseline: 'bottom', |
111
|
|
|
offsetX: 8, |
112
|
|
|
offsetY: -8, |
113
|
|
|
scale: iconScale, |
114
|
|
|
fill: new Fill({color: 'rgb(0,0,0)'}), |
115
|
|
|
font: '12px monospace bold', |
116
|
|
|
backgroundFill: new Fill({color: 'rgba(255,255,255,.4)'}) |
117
|
|
|
}), |
118
|
|
|
image: new Icon({ |
119
|
|
|
src: "./" + p.img, |
120
|
|
|
crossOrigin: '', |
121
|
|
|
opacity: p.opacity, |
122
|
|
|
scale: iconScale, |
123
|
|
|
rotation: p.angle * Math.PI / 180, |
124
|
|
|
}), |
125
|
|
|
})); |
126
|
|
|
|
127
|
|
|
vectorSource.addFeature(f); |
128
|
|
|
}); |
129
|
|
|
|
130
|
|
|
// if (mapOpts.kmlfile.length > 0) { |
131
|
|
|
const kmlLayer = new VectorLayer({ |
132
|
|
|
source: new VectorSource({ |
133
|
|
|
url: './sitemap.kml', |
134
|
|
|
format: new KML() |
135
|
|
|
}), |
136
|
|
|
title: 'KML ' + mapOpts.kmlfile.split(/[\\\/]/).pop().split(/[.]/)[0], |
137
|
|
|
}); |
138
|
|
|
//map.addLayer(kmlLayer); |
139
|
|
|
overlayGroup.getLayers().push(kmlLayer); |
140
|
|
|
// } |
141
|
|
|
|
142
|
|
|
|
143
|
|
|
if (mapOpts.gpxfile.length > 0) { |
144
|
|
|
const gpxStyle = { |
145
|
|
|
'Point': new Style({ |
146
|
|
|
image: new CircleStyle({ |
147
|
|
|
fill: new Fill({ |
148
|
|
|
color: 'rgba(0,153,255,.7)', |
149
|
|
|
}), |
150
|
|
|
radius: 4, |
151
|
|
|
stroke: new Stroke({ |
152
|
|
|
color: 'rgba(0,0,255,.7)', |
153
|
|
|
width: 3, |
154
|
|
|
}), |
155
|
|
|
}), |
156
|
|
|
}), |
157
|
|
|
'LineString': new Style({ |
158
|
|
|
stroke: new Stroke({ |
159
|
|
|
color: 'rgba(0,0,255,.7)', |
160
|
|
|
width: 3, |
161
|
|
|
}), |
162
|
|
|
}), |
163
|
|
|
'MultiLineString': new Style({ |
164
|
|
|
stroke: new Stroke({ |
165
|
|
|
color: 'rgba(0,0,255,.7)', |
166
|
|
|
width: 3, |
167
|
|
|
}), |
168
|
|
|
}), |
169
|
|
|
}; |
170
|
|
|
const gpxLayer = new VectorLayer({ |
171
|
|
|
source: new VectorSource({ |
172
|
|
|
url: DOKU_BASE + "lib/exe/fetch.php?media=" + mapOpts.gpxfile, |
|
|
|
|
173
|
|
|
format: new GPX(), |
174
|
|
|
}), |
175
|
|
|
style: function (feature) { |
176
|
|
|
return gpxStyle[feature.getGeometry().getType()]; |
177
|
|
|
}, |
178
|
|
|
title: 'GPX ' + mapOpts.gpxfile.split(/[\\\/]/).pop().split(/[.]/)[0], |
179
|
|
|
}); |
180
|
|
|
// map.addLayer(gpxLayer); |
181
|
|
|
overlayGroup.getLayers().push(gpxLayer); |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
|
185
|
|
|
const container = document.getElementById('popup'); |
186
|
|
|
const content = document.getElementById('popup-content'); |
187
|
|
|
const closer = document.getElementById('popup-closer'); |
188
|
|
|
|
189
|
|
|
const overlay = new Overlay({ |
190
|
|
|
element: container, |
191
|
|
|
autoPan: true, |
192
|
|
|
autoPanAnimation: { |
193
|
|
|
duration: 250, |
194
|
|
|
}, |
195
|
|
|
//stopEvent: false, |
196
|
|
|
}); |
197
|
|
|
map.addOverlay(overlay); |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Add a click handler to hide the popup. |
201
|
|
|
* @return {boolean} Don't follow the href. |
202
|
|
|
*/ |
203
|
|
|
closer.onclick = function () { |
204
|
|
|
overlay.setPosition(undefined); |
205
|
|
|
closer.blur(); |
206
|
|
|
return false; |
207
|
|
|
}; |
208
|
|
|
|
209
|
|
|
|
210
|
|
|
// display popup on click |
211
|
|
|
map.on('click', function (evt) { |
212
|
|
|
const selFeature = map.forEachFeatureAtPixel(evt.pixel, function (feature) { |
213
|
|
|
return feature; |
214
|
|
|
}); |
215
|
|
|
if (selFeature) { |
216
|
|
|
console.debug('found feature: ', selFeature); |
217
|
|
|
overlay.setPosition(evt.coordinate); |
218
|
|
|
|
219
|
|
|
let pContent = '<div class="spacer"> </div>'; |
220
|
|
|
let locDesc = ''; |
221
|
|
|
|
222
|
|
|
if (selFeature.get('rowId') !== undefined) { |
223
|
|
|
pContent += '<span class="rowId">' + selFeature.get('rowId') + ': </span>'; |
224
|
|
|
} |
225
|
|
|
if (selFeature.get('name') !== undefined) { |
226
|
|
|
pContent += '<span class="txt">' + selFeature.get('name') + '</span>'; |
227
|
|
|
locDesc = selFeature.get('name'); |
|
|
|
|
228
|
|
|
// TODO strip <p> tag from locDesc |
229
|
|
|
// locDesc = selFeature.get('name').split(/\s+/).slice(0,2).join('+'); |
230
|
|
|
} |
231
|
|
|
if (selFeature.get('ele') !== undefined) { |
232
|
|
|
pContent += '<div class="ele">elevation: ' + selFeature.get('ele') + '</div>'; |
233
|
|
|
} |
234
|
|
|
if (selFeature.get('type') !== undefined) { |
235
|
|
|
pContent += '<div>' + selFeature.get('type') + '</div>'; |
236
|
|
|
} |
237
|
|
|
if (selFeature.get('time') !== undefined) { |
238
|
|
|
pContent += '<div class="time">time: ' + selFeature.get('time') + '</div>'; |
239
|
|
|
} |
240
|
|
|
if (selFeature.get('description') !== undefined) { |
241
|
|
|
pContent += '<div class="desc">' + selFeature.get('description') + '</div>'; |
242
|
|
|
} |
243
|
|
|
// // mapillary layer |
244
|
|
|
// if (selFeature.attributes.location !== undefined) { |
245
|
|
|
// pContent += '<div class="desc">' + selFeature.get(location) + '</div>'; |
246
|
|
|
// } |
247
|
|
|
// // mapillary layer |
248
|
|
|
// if (selFeature.attributes.image !== undefined) { |
249
|
|
|
// pContent += '<img class="img" src=' + selFeature.get(image) + ' width="320" />'; |
250
|
|
|
// } |
251
|
|
|
// // mapillary layer |
252
|
|
|
// if (selFeature.attributes.ca !== undefined) { |
253
|
|
|
// var angle = Math.floor(selFeature.get(ca)); |
254
|
|
|
// pContent += '<div class="coord"><img src="' + DOKU_BASE + 'lib/plugins/openlayersmapoverlays/icons/arrow-up-20.png' |
255
|
|
|
// + '" width="16" height="16" style="transform:rotate(' + angle + 'deg)" alt="' + angle + 'º"/> '+OpenLayers.i18n("compass") + angle + 'º</div>'; |
256
|
|
|
// } |
257
|
|
|
// |
258
|
|
|
if (selFeature.get('img') !== undefined) { |
259
|
|
|
pContent += '<div class="coord" title="lat;lon">' + |
260
|
|
|
'<img src="' + selFeature.get('img') + '" width="16" height="16" ' + |
261
|
|
|
'style="transform:rotate(' + selFeature.get('angle') + 'deg)" /> ' |
262
|
|
|
+ '<a href="geo:' + selFeature.get('lat') + ',' + selFeature.get('lon') |
263
|
|
|
+ '?q=' + selFeature.get('lat') + ',' + selFeature.get('lon') + '(' + selFeature.get('alt') + ')" title="Open in navigation app">' |
264
|
|
|
+ format([selFeature.get('lon'), selFeature.get('lat')], '{x}º; {y}º', 4) + '</a></div>'; |
265
|
|
|
} |
266
|
|
|
content.innerHTML = pContent; |
267
|
|
|
} else { |
|
|
|
|
268
|
|
|
// do nothing?... |
269
|
|
|
} |
270
|
|
|
}); |
271
|
|
|
|
272
|
|
|
// change mouse cursor when over marker |
273
|
|
|
map.on('pointermove', function (e) { |
274
|
|
|
const pixel = map.getEventPixel(e.originalEvent); |
275
|
|
|
const hit = map.hasFeatureAtPixel(pixel); |
276
|
|
|
map.getTarget().style.cursor = hit ? 'pointer' : ''; |
277
|
|
|
}); |
278
|
|
|
|
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.