@phila/layerboard 2.2.0 → 3.0.0-beta.1

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.
@@ -1,1108 +0,0 @@
1
- <template>
2
- <div
3
- id="map-panel-container"
4
- :class="mapPanelContainerClass"
5
- :style="mapPanelContainerStyle"
6
- >
7
- <full-screen-map-toggle-tab v-once />
8
- <map_
9
- id="map-tag"
10
- :class="{ 'mb-map-with-widget': this.$store.state.cyclomedia.active || this.$store.state.pictometry.active }"
11
- :center="mapCenter"
12
- :zoom="this.$store.state.map.zoom"
13
- :zoom-control-position="zoomControlPosition"
14
- :min-zoom="this.$config.map.minZoom"
15
- :max-zoom="22"
16
- @l-click="handleMapClick"
17
- @l-moveend="handleMapMove"
18
- >
19
- <!-- <polygon_ -->
20
- <polygon_
21
- v-if="selectedPopupLayerGeometryType === 'Polygon' || selectedPopupLayerGeometryType === 'MultiPolygon'"
22
- :color="'#00ffff'"
23
- :fill="false"
24
- :weight="5"
25
- :latlngs="selectedPopupLayerCoordinatesFlipped"
26
- :pane="'highlightOverlay'"
27
- />
28
- <polyline_
29
- v-if="selectedPopupLayerGeometryType === 'LineString'"
30
- :color="'#00ffff'"
31
- :weight="4"
32
- :latlngs="selectedPopupLayerCoordinatesFlipped"
33
- :pane="'highlightOverlay'"
34
- />
35
- <circle-marker
36
- v-if="selectedPopupLayerGeometryType === 'Point'"
37
- :latlng="selectedPopupLayerCoordinatesFlipped"
38
- :radius="7"
39
- :fill-color="'#00ffff'"
40
- :color="'#00ffff'"
41
- :weight="locationMarker.weight"
42
- :opacity="locationMarker.opacity"
43
- :fill-opacity="locationMarker.fillOpacity"
44
- :pane="'highlightOverlay'"
45
- />
46
-
47
- <!-- webmap -->
48
- <esri-web-map>
49
- <esri-web-map-layer
50
- v-for="(layer, key) in this.$store.state.map.webMapLayersAndRest"
51
- v-if="shouldShowFeatureLayer(layer)"
52
- :key="key"
53
- :layer="layer.layer"
54
- :layer-name="layer.title"
55
- :layer-definition="layer.rest.layerDefinition"
56
- :opacity="layer.opacity"
57
- :type="layer.type2"
58
- :layer-options="layer.options"
59
- />
60
- </esri-web-map>
61
- <popup v-if="shouldShowPopup">
62
- <popup-content />
63
- </popup>
64
-
65
-
66
- <!-- basemaps -->
67
- <esri-tiled-map-layer
68
- v-for="(basemap, key) in this.$config.map.basemaps"
69
- v-if="activeBasemap === key"
70
- :key="key"
71
- :name="key"
72
- :url="basemap.url"
73
- :max-zoom="basemap.maxZoom"
74
- :z-index="basemap.zIndex"
75
- :attribution="basemap.attribution"
76
- />
77
-
78
- <!-- basemap labels and parcels outlines -->
79
- <esri-tiled-map-layer
80
- v-for="(tiledLayer, key) in this.$config.map.tiledLayers"
81
- v-if="activeTiles.includes(key)"
82
- :key="key"
83
- :name="key"
84
- :url="tiledLayer.url"
85
- :z-index="tiledLayer.zIndex"
86
- :attribution="tiledLayer.attribution"
87
- />
88
-
89
- <esri-tiled-map-layer
90
- v-for="(tiledLayer, key) in currentTiledLayers"
91
- :key="key"
92
- :name="key"
93
- :url="tiledLayer.url"
94
- :z-index="tiledLayer.zIndex"
95
- :attribution="tiledLayer.attribution"
96
- />
97
-
98
- <vector-marker
99
- v-for="marker in markers"
100
- :key="marker.key"
101
- :latlng="marker.latlng"
102
- :marker-color="marker.color"
103
- :icon="marker.icon"
104
- />
105
-
106
- <!-- marker showing last click -->
107
- <vector-marker
108
- v-if="clickMarker.latlng[0] !== null"
109
- :latlng="clickMarker.latlng"
110
- :marker-color="clickMarker.color"
111
- :icon="clickMarker.icon"
112
- />
113
-
114
- <!-- marker using a png and ablility to rotate it -->
115
- <png-marker
116
- v-if="cyclomediaActive"
117
- :icon="'images/camera.png'"
118
- :latlng="cycloLatlng"
119
- :rotation-angle="cycloRotationAngle"
120
- />
121
-
122
- <!-- marker using custom code extending icons - https://github.com/iatkin/leaflet-svgicon -->
123
- <svg-view-cone-marker
124
- v-if="cyclomediaActive"
125
- :latlng="cycloLatlng"
126
- :rotation-angle="cycloRotationAngle"
127
- :h-fov="cycloHFov"
128
- />
129
-
130
- <control-corner
131
- :v-side="'top'"
132
- :h-side="'almostright'"
133
- />
134
-
135
- <control-corner
136
- :v-side="'top'"
137
- :h-side="'almostleft'"
138
- />
139
-
140
- <control-corner
141
- :v-side="'bottom'"
142
- :h-side="'furtherleft'"
143
- />
144
-
145
- <div v-once>
146
- <location-control
147
- v-if="geolocationEnabled"
148
- v-once
149
- :position="locationControlPosition"
150
- @click="handleButtonClick"
151
- />
152
- </div>
153
-
154
- <div v-once>
155
- <basemap-toggle-control
156
- v-if="shouldShowImageryToggle"
157
- v-once
158
- :position="basemapToggleControlPosition"
159
- />
160
- </div>
161
-
162
- <div v-once>
163
- <basemap-select-control :position="basemapSelectControlPosition" />
164
- </div>
165
-
166
- <div v-once>
167
- <pictometry-button
168
- v-if="shouldShowPictometryButton"
169
- v-once
170
- :position="'topright'"
171
- :link="'pictometry'"
172
- :img-src="'images/pictometry.png'"
173
- />
174
- </div>
175
-
176
- <div v-once>
177
- <cyclomedia-button
178
- v-if="shouldShowCyclomediaButton"
179
- v-once
180
- :position="cyclomediaButtonPosition"
181
- :link="'cyclomedia'"
182
- :img-src="'images/cyclomedia.png'"
183
- @handle-cyclomedia-button-click="handleCyclomediaButtonClick"
184
- />
185
- </div>
186
-
187
- <div
188
- v-if="measureControlEnabled"
189
- v-once
190
- >
191
- <measure-control :position="'bottomleft'" />
192
- </div>
193
-
194
- <!-- search control -->
195
- <div v-once>
196
- <map-address-input
197
- :position="addressInputPosition"
198
- :placeholder="addressInputPlaceholder"
199
- :width-from-config="addressInputWidth"
200
- @handle-search-form-submit="handleSearchFormSubmit"
201
- />
202
- </div>
203
- <map-address-candidate-list
204
- v-if="addressAutocompleteEnabled"
205
- :position="addressInputPosition"
206
- :width-from-config="addressInputWidth"
207
- />
208
-
209
- <!-- location marker -->
210
- <circle-marker
211
- v-if="this.$store.state.map.location.lat != null"
212
- :latlng="locationMarker.latlng"
213
- :radius="locationMarker.radius"
214
- :fill-color="locationMarker.fillColor"
215
- :color="locationMarker.color"
216
- :weight="locationMarker.weight"
217
- :opacity="locationMarker.opacity"
218
- :fill-opacity="locationMarker.fillOpacity"
219
- :pane="'highlightOverlay'"
220
- />
221
-
222
- <cyclomedia-recording-circle
223
- v-for="recording in cyclomediaRecordings"
224
- v-if="cyclomediaActive"
225
- :key="recording.imageId"
226
- :image-id="recording.imageId"
227
- :latlng="[recording.lat, recording.lng]"
228
- :size="1.2"
229
- :color="'#3388ff'"
230
- :weight="1"
231
- @l-click="handleCyclomediaRecordingClick"
232
- />
233
- </map_>
234
- <modal-about />
235
- <slot
236
- class="widget-slot"
237
- name="cycloWidget"
238
- />
239
- <slot
240
- class="widget-slot"
241
- name="pictWidget"
242
- />
243
- </div>
244
- </template>
245
-
246
- <script>
247
- import 'leaflet/dist/leaflet.css';
248
-
249
- import {
250
- LatLngBounds,
251
- } from 'leaflet';
252
-
253
- // import { geoJSON, featureGroup } from 'leaflet';
254
- // import { marker as Lmarker } from 'leaflet';
255
-
256
- // mixins
257
- import markersMixin from './markers-mixin';
258
- import cyclomediaMixin from '@phila/vue-mapping/src/cyclomedia/map-panel-mixin.js';
259
- import pictometryMixin from '@phila/vue-mapping/src/pictometry/map-panel-mixin.js';
260
-
261
- // components
262
- import CyclomediaRecordingsClient from '@phila/vue-mapping/src/cyclomedia/recordings-client.js';
263
- import ControlCorner from '@phila/vue-mapping/src/leaflet/ControlCorner.vue';
264
- import FullScreenMapToggleTab from '@phila/vue-mapping/src/components/FullScreenMapToggleTab.vue';
265
- import Map_ from '@phila/vue-mapping/src/leaflet/Map.vue';
266
- import LocationControl from '@phila/vue-mapping/src/components/LocationControl.vue';
267
- import BasemapToggleControl from '@phila/vue-mapping/src/components/BasemapToggleControl.vue';
268
- import BasemapSelectControl from '@phila/vue-mapping/src/components/BasemapSelectControl.vue';
269
- import PictometryButton from '@phila/vue-mapping/src/pictometry/Button.vue';
270
- import CyclomediaButton from '@phila/vue-mapping/src/cyclomedia/Button.vue';
271
- import MeasureControl from '@phila/vue-mapping/src/components/MeasureControl.vue';
272
- // import LegendControl from '@phila/vue-mapping/src/components/LegendControl.vue';
273
- import MapAddressInput from '@phila/vue-mapping/src/components/MapAddressInput.vue';
274
-
275
- import Popup from '@phila/vue-mapping/src/leaflet/Popup.vue';
276
- import PopupContent from '@phila/vue-mapping/src/leaflet/PopupContent.vue';
277
-
278
- import EsriWebMap from '@phila/vue-mapping/src/esri-leaflet/EsriWebMap.vue';
279
- import EsriWebMapLayer from '@phila/vue-mapping/src/esri-leaflet/EsriWebMapLayer.vue';
280
-
281
- export default {
282
- name: 'MapPanel',
283
- components: {
284
- MapAddressCandidateList: () => import(/* webpackChunkName: "lbmp_pvm_MapAddressCandidateList" */'@phila/vue-mapping/src/components/MapAddressCandidateList.vue'),
285
- EsriTiledMapLayer: () => import(/* webpackChunkName: "lbmp_pvm_EsriTiledMapLayer" */'@phila/vue-mapping/src/esri-leaflet/TiledMapLayer.vue'),
286
- ModalAbout: () => import(/* webpackChunkName: "lbmp_pvm_ModalAbout" */'@phila/vue-mapping/src/components/ModalAbout.vue'),
287
- CircleMarker: () => import(/* webpackChunkName: "lbmp_pvm_CircleMarker" */'@phila/vue-mapping/src/leaflet/CircleMarker.vue'),
288
- VectorMarker: () => import(/* webpackChunkName: "lbmp_pvm_VectorMarker" */'@phila/vue-mapping/src/components/VectorMarker.vue'),
289
- PngMarker: () => import(/* webpackChunkName: "lbmp_pvm_PngMarker" */'@phila/vue-mapping/src/components/PngMarker.vue'),
290
- CyclomediaRecordingCircle: () => import(/* webpackChunkName: "lbmp_pvm_CyclomediaRecordingCircle" */'@phila/vue-mapping/src/cyclomedia/RecordingCircle.vue'),
291
- SvgViewConeMarker: () => import(/* webpackChunkName: "lbmp_pvm_CyclomediaSvgViewConeMarker" */'@phila/vue-mapping/src/cyclomedia/SvgViewConeMarker.vue'),
292
- EsriWebMap,
293
- EsriWebMapLayer,
294
- ControlCorner,
295
- FullScreenMapToggleTab,
296
- Map_,
297
- LocationControl,
298
- BasemapToggleControl,
299
- BasemapSelectControl,
300
- PictometryButton,
301
- CyclomediaButton,
302
- MeasureControl,
303
- MapAddressInput,
304
- Popup,
305
- PopupContent,
306
- Polygon_: () => import(/* webpackChunkName: "lbmp_pvm_Polygon_" */'@phila/vue-mapping/src/leaflet/Polygon.vue'),
307
- Polyline_: () => import(/* webpackChunkName: "lbmp_pvm_Polyline_" */'@phila/vue-mapping/src/leaflet/Polyline.vue'),
308
- // Control: () => import(/* webpackChunkName: "lbmp_pvm_Control" */'@phila/vue-mapping/src/leaflet/Control.vue'),
309
- // LegendControl,
310
- // Geojson: () => import(/* webpackChunkName: "lbmp_pvm_Geojson" */'@phila/vue-mapping/src/leaflet/Geojson.vue'),
311
- // BasemapTooltip: () => import(/* webpackChunkName: "lbmp_pvm_BasemapTooltip" */'@phila/vue-mapping/src/components/BasemapTooltip.vue'),
312
- // EsriFeatureLayer: () => import(/* webpackChunkName: "lbmp_pvm_EsriFeatureLayer" */'@phila/vue-mapping/src/esri-leaflet/FeatureLayer.vue'),
313
- // EsriTiledOverlay: () => import(/* webpackChunkName: "lbmp_pvm_EsriTiledOverlay" */'@phila/vue-mapping/src/esri-leaflet/TiledOverlay.vue'),
314
- // EsriDynamicMapLayer: () => import(/* webpackChunkName: "lbmp_pvm_EsriDynamicMapLayer" */'@phila/vue-mapping/src/esri-leaflet/DynamicMapLayer.vue'),
315
- // EsriWebMap: () => import(/* webpackChunkName: "lbmp_pvm_EsriWebMap" */'@phila/vue-mapping/src/esri-leaflet/EsriWebMap.vue'),
316
- // EsriWebMapLayer: () => import(/* webpackChunkName: "lbmp_pvm_EsriWebMapLayer" */'@phila/vue-mapping/src/esri-leaflet/EsriWebMapLayer.vue'),
317
- },
318
- mixins: [
319
- markersMixin,
320
- cyclomediaMixin,
321
- pictometryMixin,
322
- ],
323
- data() {
324
- const windowHeight = window.innerHeight;
325
- const siteHeaderHeightNum = parseInt(document.getElementsByClassName('site-header')[0].getBoundingClientRect().height);
326
- console.log('siteHeaderHeightNum:', siteHeaderHeightNum);
327
- // const appFooterHeightNum = parseInt(document.getElementsByClassName('app-footer')[0].getBoundingClientRect().height);
328
- const appFooterHeightNum = 36;
329
- // console.log('appFooterHeightNum:', appFooterHeightNum);
330
- // console.log(document.getElementsByClassName('datasets-button'))
331
- // const datasetsButtonHeightNum = parseInt(document.getElementsByClassName('datasets-button')[0].getBoundingClientRect().height);
332
- // console.log('datasetsButtonHeightNum:', datasetsButtonHeightNum);
333
- let mapPanelHeight = windowHeight - siteHeaderHeightNum - appFooterHeightNum - 36;
334
- let mapPanelHeightStr = mapPanelHeight.toString() + 'px';
335
- console.log('mapPanelHeightStr:', mapPanelHeightStr);
336
-
337
- const data = {
338
- mapPanelContainerStyle: {
339
- 'height': mapPanelHeightStr,
340
- 'min-height': mapPanelHeightStr,
341
- },
342
- };
343
- return data;
344
- },
345
- computed: {
346
- currentTiledLayers() {
347
- // console.log('currentTiledLayers is computing, this.activeTopicConfig.tiledLayers:', this.activeTopicConfig.tiledLayers);
348
- let val = [];
349
- if (this.activeTopicConfig.tiledLayers) {
350
- let topicLayers = this.activeTopicConfig.tiledLayers;
351
- for (let topicLayer of topicLayers) {
352
- if (this.$store.state.map.tiledLayers.includes(topicLayer)) {
353
- val.push(this.$config.map.tiledLayers[topicLayer]);
354
- }
355
- }
356
- }
357
- return val;
358
- },
359
- geocodeZoom() {
360
- if (this.$config.map.geocodeZoom) {
361
- return this.$config.map.geocodeZoom;
362
- }
363
- return 19;
364
-
365
- },
366
- windowDim() {
367
- return this.$store.state.windowDimensions;
368
- },
369
- mapCenter() {
370
- return this.$store.state.map.center;
371
- },
372
- addressAutocompleteEnabled() {
373
- // TODO tidy up the code
374
- if (this.$config.addressInput) {
375
- if (this.$config.addressInput.autocompleteEnabled === true) {
376
- return true;
377
- }
378
- return false;
379
-
380
- }
381
- return false;
382
-
383
- },
384
- addressInputPosition() {
385
- if (this.isMobileOrTablet) {
386
- return 'topleft';
387
- }
388
- return 'topalmostleft';
389
-
390
- },
391
- addressInputWidth() {
392
- if (this.$config.addressInput) {
393
- return this.$config.addressInput.mapWidth;
394
- }
395
- return 415;
396
-
397
- },
398
- addressInputPlaceholder() {
399
- if (this.$config.addressInput) {
400
- return this.$config.addressInput.placeholder;
401
- }
402
- return null;
403
- },
404
- basemapToggleControlPosition() {
405
- let value = 'topright';
406
- if (this.$config.map.basemapToggleControlPosition) {
407
- value = this.$config.map.basemapToggleControlPosition;
408
- }
409
- return value;
410
- },
411
- cyclomediaButtonPosition() {
412
- let value = 'topright';
413
- if (this.$config.cyclomedia.buttonPosition) {
414
- value = this.$config.cyclomedia.buttonPosition;
415
- }
416
- return value;
417
- },
418
- locationControlPosition() {
419
- let value = 'bottomright';
420
- if (this.$config.geolocation.buttonPosition) {
421
- value = this.$config.geolocation.buttonPosition;
422
- }
423
- return value;
424
- },
425
- zoomControlPosition() {
426
- let value = 'bottomright';
427
- if (this.$config.map.zoomControlPosition) {
428
- value = this.$config.map.zoomControlPosition;
429
- }
430
- return value;
431
- },
432
- basemapSelectControlPosition() {
433
- let value = 'topalmostright';
434
- if (this.$config.map.basemapSelectControlPosition) {
435
- value = this.$config.map.basemapSelectControlPosition;
436
- } else if (this.isMobileOrTablet) {
437
- value = 'topright';
438
- }
439
- return value;
440
- },
441
- isMobileOrTablet() {
442
- return this.$store.state.isMobileOrTablet;
443
- },
444
- fullScreenMapEnabled() {
445
- return this.$store.state.fullScreenMapEnabled;
446
- },
447
- // windowWidth() {
448
- // return this.$store.state.windowWidth;
449
- // },
450
- topics() {
451
- let configTopics = [];
452
- if (this.$config.topics) {
453
- for (let topic of this.$config.topics) {
454
- configTopics.push(topic.label);
455
- }
456
- } else {
457
- configTopics = null;
458
- }
459
- return configTopics;
460
- },
461
- activeTopic() {
462
- return this.$store.state.activeTopic;
463
- },
464
- activeTopicConfig() {
465
- const key = this.activeTopic;
466
- const createdComplete = this.createdComplete;
467
- // console.log('computed activeTopicConfig is running, this.$config:', this.$config, 'key:', key, 'createdComplete:', createdComplete);
468
- let config;
469
-
470
- // if no active topic, return null
471
- if (key && this.$config) {
472
- config = this.$config.topics.filter((topic) => {
473
- return topic.key === key;
474
- })[0];
475
- }
476
-
477
- return config || {};
478
- },
479
- activeTopicLayers() {
480
- console.log('activeTopicLayers computed');
481
- if (!this.topics) {
482
- // if there are no topics, return all layers
483
- let titles = [];
484
- for (let layer of this.$store.state.map.webMapLayersAndRest) {
485
- titles.push(layer.title);
486
- }
487
- return titles;
488
- } else if (this.topics && !this.activeTopic) {
489
- // if there are topics, but none is open, return no layers
490
- return [];
491
- }
492
- const activeTopicConfigComponents = this.activeTopicConfig.components;
493
- let topicLayers;
494
- for (let component of activeTopicConfigComponents) {
495
- if (component.type === 'checkbox-set' || component.type === 'radio-button-set') {
496
- topicLayers = component.options.topicLayers;
497
- // console.log('in activeTopicLayers computed, topicLayers:', topicLayers);
498
- }
499
- }
500
- let topicLayersKeys = [];
501
- if (topicLayers) {
502
- for (let topicLayer of topicLayers) {
503
- // topicLayersKeys.push(topicLayer.title);
504
- topicLayersKeys.push(this.evaluateSlot(topicLayer.title));
505
- }
506
- }
507
- // console.log('topicLayers:', topicLayers, 'topicLayersKeys:', topicLayersKeys);
508
- return topicLayersKeys;
509
- },
510
- mapPanelContainerClass() {
511
- if (this.fullScreenMapEnabled) {
512
- return 'medium-24 small-order-1 small-24 medium-order-2 mb-panel mb-panel-map';
513
- } else if (this.windowDim.width >= 950) {
514
- return 'medium-16 small-order-1 small-24 medium-order-2 mb-panel mb-panel-map';
515
- }
516
- return 'medium-14 small-order-1 small-24 medium-order-2 mb-panel mb-panel-map';
517
-
518
- },
519
- cycloLatlng() {
520
- if (this.$store.state.cyclomedia.orientation.xyz !== null) {
521
- const xyz = this.$store.state.cyclomedia.orientation.xyz;
522
- return [ xyz[1], xyz[0] ];
523
- }
524
- const center = this.$config.map.center;
525
- return center;
526
-
527
- },
528
- cycloRotationAngle() {
529
- return this.$store.state.cyclomedia.orientation.yaw;// * (180/3.14159265359);
530
- },
531
- cycloHFov() {
532
- return this.$store.state.cyclomedia.orientation.hFov;
533
- },
534
- shouldShowCyclomediaButton() {
535
- return this.$config.cyclomedia.enabled && !this.isMobileOrTablet;
536
- },
537
- shouldShowPictometryButton() {
538
- return this.$config.pictometry.enabled && !this.isMobileOrTablet;
539
- },
540
- shouldShowPopup() {
541
- if (this.intersectingFeatures.length > 0) {
542
- return true;
543
- }
544
- return false;
545
-
546
- },
547
- selectedPopupLayer() {
548
- return this.$store.state.map.selectedPopupLayer;
549
- },
550
- selectedPopupLayerGeometryType() {
551
- if (this.selectedPopupLayer) {
552
- return this.selectedPopupLayer.feature.geometry.type;
553
- }
554
- return null;
555
-
556
- },
557
- selectedPopupLayerCoordinates() {
558
- let coordinates;
559
- if (this.selectedPopupLayerGeometryType === "Point" || this.selectedPopupLayerGeometryType === "LineString") {
560
- coordinates = this.selectedPopupLayer.feature.geometry.coordinates;
561
- } else if (this.selectedPopupLayerGeometryType === "Polygon") {
562
- coordinates = this.selectedPopupLayer.feature.geometry.coordinates[0];
563
- } else if (this.selectedPopupLayerGeometryType === "MultiPolygon") {
564
- coordinates = this.selectedPopupLayer.feature.geometry.coordinates;
565
- }
566
- return coordinates;
567
- },
568
- selectedPopupLayerCoordinatesFlipped() {
569
- // console.log('coords:', this.flipCoordsArray(this.selectedPopupLayerCoordinates));
570
- if (this.selectedPopupLayerGeometryType === "Point") {
571
- return this.flipCoords(this.selectedPopupLayerCoordinates);
572
- } else if (this.selectedPopupLayerGeometryType !== "MultiPolygon") {
573
- // console.log('calling FlipCoordsArray on:', this.selectedPopupLayerCoordinates);
574
- return this.flipCoordsArray(this.selectedPopupLayerCoordinates);
575
- }
576
- return this.flipCoordsMultiPolygon(this.selectedPopupLayerCoordinates);
577
-
578
- },
579
- intersectingFeatures() {
580
- return this.$store.state.map.intersectingFeatures;
581
- },
582
- geolocationEnabled() {
583
- return this.$config.geolocation.enabled;
584
- },
585
- scale() {
586
- return this.$store.state.map.scale;
587
- },
588
- webMapActiveLayers() {
589
- return this.$store.state.map.webMapActiveLayers;
590
- },
591
- activeBasemap() {
592
- const shouldShowBasemapSelectControl = this.$store.state.map.shouldShowBasemapSelectControl;
593
- if (shouldShowBasemapSelectControl) {
594
- return this.$store.state.map.imagery;
595
- }
596
- const defaultBasemap = this.$config.map.defaultBasemap;
597
- const basemap = this.$store.state.map.basemap || defaultBasemap;
598
- return basemap;
599
- },
600
- activeTiles() {
601
- if (this.$config.map.basemaps[this.activeBasemap]) {
602
- return this.$config.map.basemaps[this.activeBasemap].tiledLayers;
603
- }
604
- return [];
605
-
606
- },
607
- basemaps() {
608
- return Object.values(this.$config.map.basemaps);
609
- },
610
- shouldShowImageryToggle() {
611
- return this.hasImageryBasemaps && this.$config.map.imagery.enabled;
612
- },
613
- imageryBasemaps() {
614
- return this.basemaps.filter(basemap => basemap.type === 'imagery');
615
- },
616
- hasImageryBasemaps() {
617
- return this.imageryBasemaps.length > 0;
618
- },
619
- imageryYears() {
620
- // pluck year from basemap objects
621
- return this.imageryBasemaps.map(x => x.year);
622
- },
623
- historicBasemaps() {
624
- return this.basemaps.filter(basemap => basemap.type === 'historic');
625
- },
626
- hasHistoricBasemaps() {
627
- return this.historicBasemaps.length > 0;
628
- },
629
- historicYears() {
630
- return this.historicBasemaps.map(x => x.year);
631
- },
632
- geocodeResult() {
633
- return this.$store.state.geocode.data;
634
- },
635
- geocodeGeom() {
636
- return (this.geocodeResult || {}).geometry;
637
- },
638
- picOrCycloActive() {
639
- if (this.cyclomediaActive || this.pictometryActive) {
640
- return true;
641
- }
642
- return false;
643
-
644
- },
645
- measureControlEnabled() {
646
- if (this.$config.map.measureControlEnabled === false) {
647
- return false;
648
- }
649
- return true;
650
- },
651
- },
652
- watch: {
653
- // mapCenter(nextMapCenter) {
654
- // console.log('MapPanel.vue watch mapCenter is firing, nextMapCenter:', nextMapCenter);
655
- // let map = this.$store.state.map.map;
656
- // let center = L.latLng(nextMapCenter[1], nextMapCenter[0]);
657
- // map.setView(center);
658
- // },
659
- windowDim(nextDim) {
660
- // console.log('mapPanel windowDim watch is firing, nextDim:', nextDim);
661
- this.handleWindowResize(nextDim);
662
- },
663
- picOrCycloActive(value) {
664
- this.$nextTick(() => {
665
- this.$store.state.map.map.invalidateSize();
666
- });
667
- },
668
- geocodeResult(nextGeocodeResult) {
669
- // console.log('watch geocodeResult, nextGeocodeResult:', nextGeocodeResult);//, 'nextGeocodeResult._featureId:', nextGeocodeResult._featureId);
670
- if (nextGeocodeResult && nextGeocodeResult._featureId) {
671
- this.$store.commit('setMapCenter', nextGeocodeResult.geometry.coordinates);
672
- this.$store.commit('setMapZoom', this.geocodeZoom);
673
- } else {
674
- this.$store.commit('setBasemap', 'pwd');
675
- }
676
- },
677
- },
678
- created() {
679
- // if there's a default address, navigate to it
680
- const defaultAddress = this.$config.defaultAddress;
681
- if (defaultAddress) {
682
- this.$controller.goToDefaultAddress(defaultAddress);
683
- }
684
-
685
- const cyclomediaConfig = this.$config.cyclomedia || {};
686
- if (cyclomediaConfig.enabled) {
687
- // create cyclomedia recordings client
688
- this.$cyclomediaRecordingsClient = new CyclomediaRecordingsClient(
689
- this.$config.cyclomedia.recordingsUrl,
690
- this.$config.cyclomedia.username,
691
- this.$config.cyclomedia.password,
692
- 4326,
693
- );
694
- }
695
- },
696
- mounted() {
697
- this.$controller.appDidLoad();
698
- // window.addEventListener('resize', this.handleWindowResize);
699
- // this.handleWindowResize(25);
700
- },
701
- methods: {
702
- evaluateSlot(valOrGetter, transforms = [], nullValue = '') {
703
- console.log('evaluateSlot is running, this.item:', this.item, 'valOrGetter:', valOrGetter);
704
- // check for null val/getter
705
- if (!valOrGetter) {
706
- return valOrGetter;
707
- }
708
-
709
- const valOrGetterType = typeof valOrGetter;
710
- let val;
711
-
712
- // fn
713
- if (valOrGetterType === 'function') {
714
- const state = this.$store.state;
715
- const controller = this.$controller;
716
- const getter = valOrGetter;
717
-
718
- // const getterText = String(getter);
719
- // const depsRe = /state(\.\w+)+/g;
720
- // const depsText = getterText.match(depsRe);
721
- // const deps = depsText.map(eval);
722
-
723
- const item = this.item;
724
- // console.log('in evaluateSlot, item:', item);
725
-
726
- // if this comp is associated with an "item" (generally some object
727
- // from a list of things, e.g. dor parcels), pass the item itself
728
- // as well when evaluating
729
- if (item) {
730
- val = getter(state, item, controller);
731
- } else {
732
- // console.log('evaluateSlot, about to get value');
733
- val = getter(state);
734
- // console.log('state:', state, 'val:', val);
735
- }
736
- } else {
737
- val = valOrGetter;
738
- }
739
- return val;
740
- },
741
- // shouldShowTiledLayer(key) {
742
- // let value;
743
- // if (!activeTopicConfig.tiledLayers) {
744
- // value = false;
745
- // } else {
746
- // const valOrGetterType = typeof valOrGetter;
747
- // let val;
748
- //
749
- // // fn
750
- // if (valOrGetterType === 'function') {
751
- // const state = this.$store.state;
752
- // // const controller = this.$controller;
753
- // const getter = valOrGetter;
754
- //
755
- // // const getterText = String(getter);
756
- // // const depsRe = /state(\.\w+)+/g;
757
- // // const depsText = getterText.match(depsRe);
758
- // // const deps = depsText.map(eval);
759
- //
760
- // const item = this.item;
761
- // // console.log('in evaluateSlot, item:', item);
762
- //
763
- // // if this comp is associated with an "item" (generally some object
764
- // // from a list of things, e.g. dor parcels), pass the item itself
765
- // // as well when evaluating
766
- // if (item) {
767
- // val = getter(state, item);
768
- // } else {
769
- // // console.log('evaluateSlot, about to get value');
770
- // val = getter(state);
771
- // // console.log('state:', state, 'val:', val);
772
- // }
773
- // } else {
774
- // val = valOrGetter;
775
- // }
776
- // }
777
- // return value;
778
- // },
779
- handleSearchFormSubmit(value) {
780
- console.log('MapPanel.vue handleSearchFormSubmit is running');
781
- this.$controller.handleSearchFormSubmit(value);
782
- },
783
- flipCoords(coords) {
784
- // console.log('flipCoords is running on:', coords);
785
- return [ coords[1], coords[0] ];
786
- },
787
- flipCoordsArray(anArray) {
788
- // console.log('flipCoordsArray is running on:', anArray);
789
- let newArray = [];
790
- for (let i in anArray) {
791
- newArray[i] = [ anArray[i][1], anArray[i][0] ];
792
- }
793
- return newArray;
794
- },
795
- flipCoordsMultiPolygon(aMultiPolygon) {
796
- // console.log('flipCoordsMultiPolygon is running on:', aMultiPolygon);
797
- let newArrayArray = [];
798
- for (let i in aMultiPolygon) {
799
- // console.log('aMultiPolygon[i]', aMultiPolygon[i]);
800
- let newArray = [];
801
- for (let j in aMultiPolygon[i][0]) {
802
- // console.log('aMultiPolygon[i][0][j]', aMultiPolygon[i][0][j]);
803
- newArray[j] = [ aMultiPolygon[i][0][j][1], aMultiPolygon[i][0][j][0] ];
804
- }
805
- newArrayArray[i] = newArray;
806
- }
807
- return newArrayArray;
808
- },
809
- shouldShowFeatureLayer(layer) {
810
- // console.log('shouldShowFeatureLayer is running, layer:', layer);
811
- if (layer.rest.layerDefinition) {
812
- if (layer.rest.layerDefinition.minScale) {
813
- // console.log('minZoom for', layer.title, 'is', layer.rest.layerDefinition.minScale, typeof layer.rest.layerDefinition.minScale, 'and current scale is', this.scale, typeof this.scale);
814
- if (this.scale <= layer.rest.layerDefinition.minScale && this.webMapActiveLayers.includes(layer.title) && this.activeTopicLayers.includes(layer.title)) {
815
- // if (this.scale <= layer.rest.layerDefinition.minScale && this.webMapActiveLayers.includes(layer.title)) {
816
- // console.log('checkLayer used layerDefinition and is returning true for', layer.title);
817
- return true;
818
- }
819
- } else if (layer.rest.layerDefinition.drawingInfo && this.webMapActiveLayers.includes(layer.title) && this.activeTopicLayers.includes(layer.title)) {
820
- // } else if (layer.rest.layerDefinition.drawingInfo && this.webMapActiveLayers.includes(layer.title)) {
821
- return true;
822
- }
823
- } else if (this.webMapActiveLayers.includes(layer.title) && this.activeTopicLayers.includes(layer.title)) {
824
- // } else if (this.webMapActiveLayers.includes(layer.title)) {
825
- // console.log('checkLayer is returning true for', layer.title);
826
- return true;
827
- } else {
828
- return false;
829
- }
830
- },
831
- handleMapClick(e) {
832
- console.log('handle map click, e:', e);
833
- document.getElementsByClassName('pvm-search-control-input')[0].blur();
834
-
835
- if (this.$store.state.map.mode === 'clickMarker') {
836
- console.log('map was in clickMarker mode');
837
- this.setClickMarkerLocation(e);
838
- this.$store.commit('setMapMode', 'identifyFeatures');
839
- } else {
840
- this.identifyFeatures(e);
841
- }
842
- },
843
-
844
- setClickMarkerLocation(e) {
845
- const payload = {
846
- lat: e.latlng.lat,
847
- lng: e.latlng.lng,
848
- };
849
- this.$store.commit('setClickMarkerLocation', payload);
850
- },
851
-
852
- // this is used when the click should identify features
853
- identifyFeatures(e) {
854
- console.log('identifyFeatures is running, e:', e);
855
- const map = this.$store.state.map.map;
856
- // const map = this.$leafletElement;
857
- const clickBounds = new LatLngBounds(e.latlng, e.latlng);
858
- // console.log('map._layers', map._layers);
859
- let intersectingFeatures = [];
860
- let geometry;
861
- for (let layer in map._layers) {
862
- var overlay = map._layers[layer];
863
- // console.log('layer:', layer, 'overlay:', overlay);
864
- if (overlay._layers) {
865
- for (let oLayer in overlay._layers) {
866
- const feature = overlay._layers[oLayer];
867
- // console.log('feature:', feature);
868
- if (feature.feature) {
869
- geometry = feature.feature.geometry.type;
870
- // console.log('clickHandler LAYER:', layer, 'FEATURE:', feature, 'GEOMETRY:', geometry);
871
- let bounds;
872
- if (geometry === 'Polygon' || geometry === 'MultiPolygon') {
873
- // console.log('polygon or multipolygon');
874
- if (feature.contains(e.latlng)) {
875
- // console.log('about to run checkForDuplicates')
876
- this.checkForDuplicates(layer, feature, intersectingFeatures);
877
- }
878
- } else if (geometry === 'LineString') {
879
- // console.log('Line');
880
- bounds = feature.getBounds();
881
- if (bounds && clickBounds.intersects(bounds)) {
882
- this.checkForDuplicates(layer, feature, intersectingFeatures);
883
- }
884
- } else if (geometry === 'Point') {
885
- // console.log('Point');
886
- bounds = new LatLngBounds(feature._latlng, feature._latlng);
887
- if (bounds && clickBounds.intersects(bounds)) {
888
- this.checkForDuplicates(layer, feature, intersectingFeatures);
889
- }
890
- }
891
- }
892
- }
893
- }
894
- }
895
- this.$store.commit('setPopupCoords', e.latlng);
896
- this.$store.commit('setIntersectingFeatures', intersectingFeatures);
897
- },
898
- checkForDuplicates(layer, feature, intersectingFeatures) {
899
- // console.log('checkForDuplicates is running, layer:', layer, 'feature:', feature);
900
- let ids = [];
901
- for (let i = 0; i < intersectingFeatures.length; i++) {
902
- ids[i] = layer + '_' + intersectingFeatures[i].feature.id;
903
- }
904
- // console.log('layer:', layer, 'feature.feature.id:', feature.feature.id);
905
- if (!ids.includes(layer + '_' + feature.feature.id)) {
906
- // console.log('checkForDuplicates going to push to intersectingFeatures:', layer, feature.feature.id);
907
- intersectingFeatures.push(feature);
908
- }
909
- },
910
-
911
-
912
- handleButtonClick() {
913
- // console.log('handle button click is running');
914
- document.getElementsByClassName('pvm-search-control-input')[0].blur();
915
- },
916
- handleMapMove(e) {
917
- // console.log('handleMapMove is running');
918
- const map = this.$store.state.map.map;
919
-
920
- const pictometryConfig = this.$config.pictometry || {};
921
-
922
- const center = map.getCenter();
923
- const { lat, lng } = center;
924
- const coords = [ lng, lat ];
925
- const zoom = map.getZoom();
926
- this.$store.commit('setMapZoom', zoom);
927
- const scale = this.$config.map.scales[zoom];
928
- this.$store.commit('setMapScale', scale);
929
-
930
- if (pictometryConfig.enabled) {
931
- // update state for pictometry
932
- this.$store.commit('setPictometryMapCenter', coords);
933
-
934
- const zoom = map.getZoom();
935
- this.$store.commit('setPictometryMapZoom', zoom);
936
- }
937
-
938
- const cyclomediaConfig = this.$config.cyclomedia || {};
939
-
940
- if (cyclomediaConfig.enabled) {
941
- // update cyclo recordings
942
- this.updateCyclomediaRecordings();
943
- this.$store.commit('setCyclomediaLatLngFromMap', [ lat, lng ]);
944
- }
945
- },
946
- handleWindowResize(dim) {
947
- // console.log('MapPanel handleWindowResize is running, dim:', dim);
948
- const windowHeight = window.innerHeight;
949
- const siteHeaderHeightNum = parseInt(document.getElementsByClassName('site-header')[0].getBoundingClientRect().height);
950
- const appFooterHeightNum = parseInt(document.getElementsByClassName('app-footer')[0].getBoundingClientRect().height);
951
- const datasetsButtonHeightNum = parseInt(document.getElementsByClassName('datasets-button')[0].getBoundingClientRect().height);
952
- // console.log('MapPanel handleWindowResize is running, datasetsButtonHeightNum:', datasetsButtonHeightNum);
953
- let mapPanelHeight = windowHeight - siteHeaderHeightNum - appFooterHeightNum - datasetsButtonHeightNum;
954
-
955
- this.mapPanelContainerStyle.height = mapPanelHeight.toString() + 'px';
956
- this.mapPanelContainerStyle['min-height'] = mapPanelHeight.toString() + 'px';
957
- // this.mapPanelContainerStyle['overflow-y'] = 'auto';
958
- },
959
-
960
- handleCyclomediaButtonClick(e) {
961
- console.log('handleCyclomediaButtonClick is running');
962
- if (!this.cyclomediaInitializationBegun) {
963
- this.$store.commit('setCyclomediaInitializationBegun', true);
964
- }
965
- const willBeActive = !this.$store.state.cyclomedia.active;
966
-
967
- this.$store.commit('setCyclomediaActive', willBeActive);
968
-
969
- // if (this.isMobileOrTablet) {
970
- // // console.log('isMobileOrTablet is true');
971
- // if (this.$store.state.pictometry.active) {
972
- // this.$store.commit('setPictometryActive', false);
973
- // }
974
- // }
975
- },
976
-
977
- }, // end of methods
978
- }; //end of export
979
- </script>
980
-
981
- <style scoped>
982
-
983
- /* .map-panel-container {
984
- height: calc(100vh - 220px);
985
- }
986
-
987
- @media screen and (max-width: 40em) {
988
- .map-panel-container {
989
- height: calc(100vh - 256px);
990
- }
991
- } */
992
-
993
- /*this allows the loading mask to fill the div*/
994
- .mb-panel-map {
995
- position: relative;
996
- }
997
-
998
- .mb-map-with-widget {
999
- height: 50%;
1000
- }
1001
-
1002
- /* @media (max-width: 1024px) {
1003
- .mb-panel-map {
1004
- height: 600px;
1005
- }
1006
- } */
1007
-
1008
- .mb-search-control-container {
1009
- height: 48px;
1010
- border-radius: 2px;
1011
- box-shadow:0 2px 4px rgba(0,0,0,0.2),0 -1px 0px rgba(0,0,0,0.02);
1012
- }
1013
-
1014
- .mb-search-control-button {
1015
- color: #fff;
1016
- width: 50px;
1017
- background: #2176d2;
1018
- line-height: 48px;
1019
- }
1020
-
1021
- .mb-search-control-input {
1022
- /* background-color: white; */
1023
- border: 0;
1024
- /* height: 48px !important; */
1025
- /* line-height: 48px; */
1026
- padding: 15px;
1027
- /* padding-left: 15px; */
1028
- /* padding-right: 15px; */
1029
- font-family: 'Montserrat', 'Tahoma', sans-serif;
1030
- font-size: 16px;
1031
- width: 275px;
1032
- }
1033
-
1034
- /* .mb-map-with-widget {
1035
- height: 50%;
1036
- } */
1037
-
1038
- .widget-slot {
1039
- display: inline-block;
1040
- float: left;
1041
- }
1042
-
1043
- .mb-map-loading-mask {
1044
- /*display: inline;*/
1045
- position: absolute;
1046
- top: 0;
1047
- height: 100%;
1048
- width: 100%;
1049
- background: rgba(0, 0 ,0 , 0.25);
1050
- z-index: 1000;
1051
- text-align: center;
1052
- vertical-align: middle;
1053
- }
1054
-
1055
- .mb-map-loading-mask-inner {
1056
- position: absolute;
1057
- top: 40%;
1058
- left: 40%;
1059
- }
1060
-
1061
- @media screen and (max-width: 1023px) {
1062
- .mb-search-control-input {
1063
- width: 250px;
1064
- }
1065
- }
1066
-
1067
- @media screen and (max-width: 900px) {
1068
- .mb-search-control-input {
1069
- width: 200px;
1070
- }
1071
- }
1072
-
1073
- @media screen and (max-width: 800px) {
1074
- .mb-search-control-input {
1075
- width: 150px;
1076
- }
1077
- }
1078
-
1079
- @media screen and (max-width: 750px) {
1080
- .mb-search-control-input {
1081
- width: 250px;
1082
- }
1083
- }
1084
-
1085
- /* @media screen and (max-width: 639px) {
1086
- .mb-search-control-input {
1087
- width: 250px;
1088
- }
1089
- } */
1090
-
1091
- @media screen and (max-width: 450px) {
1092
- .mb-search-control-input {
1093
- width: 200px;
1094
- }
1095
- }
1096
-
1097
- @media screen and (max-width: 400px) {
1098
- .mb-search-control-input {
1099
- width: 150px;
1100
- }
1101
- }
1102
-
1103
- @media screen and (max-width: 350px) {
1104
- .mb-search-control-input {
1105
- width: 100px;
1106
- }
1107
- }
1108
- </style>