@foodmarketmaker/mapag 0.0.19 → 0.0.20
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.
- package/fesm2022/foodmarketmaker-mapag.mjs +456 -114
- package/fesm2022/foodmarketmaker-mapag.mjs.map +1 -1
- package/index.d.ts +76 -22
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ import maplibregl, { Popup } from 'maplibre-gl';
|
|
|
21
21
|
import bbox from '@turf/bbox';
|
|
22
22
|
import bboxPolygon from '@turf/bbox-polygon';
|
|
23
23
|
import buffer from '@turf/buffer';
|
|
24
|
+
import difference from '@turf/difference';
|
|
24
25
|
|
|
25
26
|
function SaveMap(map) {
|
|
26
27
|
var mapCanvas = map.getCanvas();
|
|
@@ -35,7 +36,6 @@ function AddLayer(map, layer, afterId) {
|
|
|
35
36
|
return false;
|
|
36
37
|
try {
|
|
37
38
|
if (map.getLayer(layer.id)) {
|
|
38
|
-
console.log(`Layer ${layer.id} already exists`);
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
41
|
map.addLayer(layer, afterId);
|
|
@@ -14325,99 +14325,43 @@ const mapStyles = {
|
|
|
14325
14325
|
},
|
|
14326
14326
|
};
|
|
14327
14327
|
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14333
|
-
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
obj.type === 'MultiPolygon';
|
|
14337
|
-
}
|
|
14338
|
-
function isPolygon(obj) {
|
|
14339
|
-
return typeof obj === 'object' &&
|
|
14340
|
-
obj !== null &&
|
|
14341
|
-
obj.type === 'Polygon';
|
|
14342
|
-
}
|
|
14343
|
-
function isNumber2DArray(input) {
|
|
14344
|
-
return Array.isArray(input) &&
|
|
14345
|
-
input.every(row => Array.isArray(row) &&
|
|
14346
|
-
row.every(cell => typeof cell === 'number'));
|
|
14347
|
-
}
|
|
14348
|
-
function isNumber3DArray(input) {
|
|
14349
|
-
return Array.isArray(input) &&
|
|
14350
|
-
input.every(matrix => Array.isArray(matrix) &&
|
|
14351
|
-
matrix.every(row => Array.isArray(row) &&
|
|
14352
|
-
row.every(cell => typeof cell === 'number')));
|
|
14353
|
-
}
|
|
14354
|
-
function toMultiPolygon(geom) {
|
|
14355
|
-
if (isMultiPolygon(geom)) {
|
|
14356
|
-
return geom;
|
|
14357
|
-
}
|
|
14358
|
-
if (isPolygon(geom)) {
|
|
14359
|
-
return {
|
|
14360
|
-
type: 'MultiPolygon',
|
|
14361
|
-
coordinates: [geom.coordinates]
|
|
14362
|
-
};
|
|
14363
|
-
}
|
|
14364
|
-
if (isNumber2DArray(geom)) {
|
|
14365
|
-
let raw = [geom];
|
|
14366
|
-
const coords = raw;
|
|
14367
|
-
return {
|
|
14368
|
-
type: 'MultiPolygon',
|
|
14369
|
-
coordinates: coords
|
|
14370
|
-
};
|
|
14371
|
-
}
|
|
14372
|
-
let raw = geom;
|
|
14373
|
-
const coords = raw;
|
|
14374
|
-
return {
|
|
14375
|
-
type: 'MultiPolygon',
|
|
14376
|
-
coordinates: coords
|
|
14377
|
-
};
|
|
14328
|
+
class BackgroundMaskSettings {
|
|
14329
|
+
fillColor = 'black';
|
|
14330
|
+
fillOpacity = 0.5;
|
|
14331
|
+
visible = true;
|
|
14332
|
+
beforeLayer = StandardLayersMapper.SELECTIONS;
|
|
14333
|
+
zoom = true;
|
|
14334
|
+
mask;
|
|
14335
|
+
loader = undefined;
|
|
14378
14336
|
}
|
|
14379
|
-
|
|
14380
14337
|
class BackgroundMaskMapper {
|
|
14381
14338
|
map;
|
|
14382
14339
|
count = 0;
|
|
14383
14340
|
total = 0;
|
|
14384
14341
|
source = 'mask';
|
|
14385
14342
|
layer = 'zmask';
|
|
14386
|
-
|
|
14387
|
-
|
|
14388
|
-
|
|
14389
|
-
|
|
14390
|
-
|
|
14391
|
-
|
|
14392
|
-
|
|
14393
|
-
|
|
14394
|
-
|
|
14395
|
-
|
|
14396
|
-
|
|
14397
|
-
|
|
14398
|
-
return this._fillColor;
|
|
14399
|
-
}
|
|
14400
|
-
set fillOpacity(opacity) {
|
|
14401
|
-
this.fillOpacity = opacity;
|
|
14402
|
-
this.load();
|
|
14403
|
-
}
|
|
14404
|
-
get fillOpacity() {
|
|
14405
|
-
return this._fillOpacity;
|
|
14406
|
-
}
|
|
14407
|
-
set visible(visible) {
|
|
14408
|
-
this._visible = visible;
|
|
14409
|
-
this.load();
|
|
14343
|
+
settings = signal(new BackgroundMaskSettings(), ...(ngDevMode ? [{ debugName: "settings" }] : []));
|
|
14344
|
+
constructor(settings) {
|
|
14345
|
+
if (settings) {
|
|
14346
|
+
this.settings.set({
|
|
14347
|
+
...this.settings(),
|
|
14348
|
+
...settings,
|
|
14349
|
+
});
|
|
14350
|
+
}
|
|
14351
|
+
const _ = effect(() => {
|
|
14352
|
+
const settings = this.settings();
|
|
14353
|
+
this._update(settings);
|
|
14354
|
+
}, ...(ngDevMode ? [{ debugName: "_" }] : []));
|
|
14410
14355
|
}
|
|
14411
|
-
|
|
14412
|
-
|
|
14356
|
+
update(settings) {
|
|
14357
|
+
this.settings.set({ ...this.settings(), ...settings });
|
|
14413
14358
|
}
|
|
14414
|
-
|
|
14415
|
-
this.
|
|
14359
|
+
_update(settings) {
|
|
14360
|
+
if (!this.map) {
|
|
14361
|
+
return;
|
|
14362
|
+
}
|
|
14416
14363
|
this.load();
|
|
14417
14364
|
}
|
|
14418
|
-
get beforeLayer() {
|
|
14419
|
-
return this._beforeLayer;
|
|
14420
|
-
}
|
|
14421
14365
|
onReady(map) {
|
|
14422
14366
|
this.map = map;
|
|
14423
14367
|
this.reset();
|
|
@@ -14430,11 +14374,12 @@ class BackgroundMaskMapper {
|
|
|
14430
14374
|
this.removeLayers();
|
|
14431
14375
|
}
|
|
14432
14376
|
flyToBounds() {
|
|
14433
|
-
|
|
14377
|
+
const settings = this.settings();
|
|
14378
|
+
if (this.map && settings.mask) {
|
|
14434
14379
|
// minX, minY, maxX, maxY order
|
|
14435
|
-
let bboxCoords =
|
|
14380
|
+
let bboxCoords = settings.mask.bbox;
|
|
14436
14381
|
if (!bboxCoords) {
|
|
14437
|
-
const f = feature(
|
|
14382
|
+
const f = feature(settings.mask);
|
|
14438
14383
|
bboxCoords = bbox(f);
|
|
14439
14384
|
}
|
|
14440
14385
|
const buffered = buffer(bboxPolygon(bboxCoords), 10, { units: 'miles' });
|
|
@@ -14450,17 +14395,36 @@ class BackgroundMaskMapper {
|
|
|
14450
14395
|
RemoveLayer(this.map, this.layer);
|
|
14451
14396
|
RemoveSource(this.map, this.source);
|
|
14452
14397
|
}
|
|
14453
|
-
load() {
|
|
14398
|
+
async load() {
|
|
14399
|
+
const settings = this.settings();
|
|
14400
|
+
// Check if we need to load from loader first
|
|
14401
|
+
if (!settings.mask && settings.loader) {
|
|
14402
|
+
const geomask = await settings.loader.LoadBoundary();
|
|
14403
|
+
this.update({ mask: geomask, loader: undefined });
|
|
14404
|
+
return;
|
|
14405
|
+
}
|
|
14454
14406
|
this.removeLayers();
|
|
14455
|
-
if (!
|
|
14407
|
+
if (!settings.visible) {
|
|
14456
14408
|
return;
|
|
14457
14409
|
}
|
|
14458
|
-
if (!this.map
|
|
14410
|
+
if (!this.map) {
|
|
14411
|
+
return;
|
|
14412
|
+
}
|
|
14413
|
+
if (!settings.mask) {
|
|
14459
14414
|
return;
|
|
14460
14415
|
}
|
|
14461
|
-
|
|
14462
|
-
//
|
|
14463
|
-
const
|
|
14416
|
+
const mask = settings.mask;
|
|
14417
|
+
// Use Turf's difference to cut the mask out of the world polygon
|
|
14418
|
+
const worldPolygon = bboxPolygon([-180, -90, 180, 90]);
|
|
14419
|
+
const features = [worldPolygon];
|
|
14420
|
+
for (const part of mask.coordinates) {
|
|
14421
|
+
features.push(polygon(part));
|
|
14422
|
+
}
|
|
14423
|
+
const fc = {
|
|
14424
|
+
type: 'FeatureCollection',
|
|
14425
|
+
features: features
|
|
14426
|
+
};
|
|
14427
|
+
const shape = difference(fc);
|
|
14464
14428
|
AddSource(this.map, this.source, {
|
|
14465
14429
|
type: 'geojson',
|
|
14466
14430
|
data: shape,
|
|
@@ -14470,31 +14434,28 @@ class BackgroundMaskMapper {
|
|
|
14470
14434
|
source: this.source,
|
|
14471
14435
|
type: 'fill',
|
|
14472
14436
|
paint: {
|
|
14473
|
-
'fill-color':
|
|
14474
|
-
'fill-opacity':
|
|
14437
|
+
'fill-color': settings.fillColor,
|
|
14438
|
+
'fill-opacity': settings.fillOpacity,
|
|
14475
14439
|
},
|
|
14476
|
-
},
|
|
14477
|
-
if (
|
|
14440
|
+
}, settings.beforeLayer);
|
|
14441
|
+
if (settings.zoom) {
|
|
14478
14442
|
this.flyToBounds();
|
|
14479
14443
|
}
|
|
14480
14444
|
}
|
|
14481
|
-
async setMask(mask, show = true) {
|
|
14482
|
-
|
|
14483
|
-
|
|
14484
|
-
|
|
14485
|
-
|
|
14486
|
-
|
|
14487
|
-
|
|
14488
|
-
|
|
14489
|
-
|
|
14490
|
-
|
|
14491
|
-
|
|
14492
|
-
}
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
const geomask = await loader.LoadBoundary();
|
|
14496
|
-
this.mask = geomask;
|
|
14497
|
-
this.load();
|
|
14445
|
+
// async setMask(mask: Geoloader | MultiPolygon | Polygon | number[][] | number[][][], show: boolean = true) {
|
|
14446
|
+
// if (isGeoloader(mask)) {
|
|
14447
|
+
// this.update({ mask: await mask.LoadBoundary() });
|
|
14448
|
+
// } else {
|
|
14449
|
+
// this.update({ mask: toMultiPolygon(mask) });
|
|
14450
|
+
// }
|
|
14451
|
+
// }
|
|
14452
|
+
// async loadGeoJsonFromLoader(loader: Geoloader) {
|
|
14453
|
+
// // Load the boundary from the external loader
|
|
14454
|
+
// const geomask = await loader.LoadBoundary();
|
|
14455
|
+
// this.update({ mask: geomask });
|
|
14456
|
+
// }
|
|
14457
|
+
getSettings() {
|
|
14458
|
+
return { ...this.settings() };
|
|
14498
14459
|
}
|
|
14499
14460
|
}
|
|
14500
14461
|
|
|
@@ -15404,6 +15365,7 @@ class HardinessMapper {
|
|
|
15404
15365
|
}
|
|
15405
15366
|
else {
|
|
15406
15367
|
this.map.setLayoutProperty(this.LAYER_ID, 'visibility', 'none');
|
|
15368
|
+
return;
|
|
15407
15369
|
}
|
|
15408
15370
|
// Update paint properties
|
|
15409
15371
|
this.map.setPaintProperty(this.LAYER_ID, 'fill-color', [
|
|
@@ -15611,6 +15573,334 @@ class NAASSettings {
|
|
|
15611
15573
|
autoSelectLayer = false;
|
|
15612
15574
|
}
|
|
15613
15575
|
|
|
15576
|
+
class NaicsMapperSettings {
|
|
15577
|
+
type = 'circle';
|
|
15578
|
+
visible = true;
|
|
15579
|
+
radius = 8;
|
|
15580
|
+
color = '#1f77b4';
|
|
15581
|
+
opacity = 0.8;
|
|
15582
|
+
strokeWidth = 1;
|
|
15583
|
+
strokeColor = '#ffffff';
|
|
15584
|
+
iconUrl = '';
|
|
15585
|
+
iconName = 'naics-icon';
|
|
15586
|
+
iconSize = 0.8;
|
|
15587
|
+
iconAllowOverlap = true;
|
|
15588
|
+
iconSdf = false;
|
|
15589
|
+
}
|
|
15590
|
+
class NaicsMapper {
|
|
15591
|
+
legends = [];
|
|
15592
|
+
count = 0;
|
|
15593
|
+
total = 0;
|
|
15594
|
+
map;
|
|
15595
|
+
svc;
|
|
15596
|
+
id;
|
|
15597
|
+
name;
|
|
15598
|
+
static pmtilesUrl = 'https://foodmarketmaker-upload-data.s3.amazonaws.com/tiles/secondary_101124.pmtiles';
|
|
15599
|
+
static sourceLayer = 'secondary_101124';
|
|
15600
|
+
SOURCE_ID = 'naics-pmtiles';
|
|
15601
|
+
sourceLayer = NaicsMapper.sourceLayer;
|
|
15602
|
+
CIRCLE_LAYER_ID;
|
|
15603
|
+
ICON_LAYER_ID;
|
|
15604
|
+
HEATMAP_LAYER_ID;
|
|
15605
|
+
currentFilter;
|
|
15606
|
+
settings = signal(new NaicsMapperSettings(), ...(ngDevMode ? [{ debugName: "settings" }] : []));
|
|
15607
|
+
constructor(settings, id = 'naics-' + Math.random().toString(36)) {
|
|
15608
|
+
this.id = id;
|
|
15609
|
+
this.name = `NAICS Mapper (${id})`;
|
|
15610
|
+
// Make layer IDs unique per instance
|
|
15611
|
+
this.CIRCLE_LAYER_ID = `${id}-circles`;
|
|
15612
|
+
this.ICON_LAYER_ID = `${id}-icons`;
|
|
15613
|
+
this.HEATMAP_LAYER_ID = `${id}-heatmap`;
|
|
15614
|
+
if (settings) {
|
|
15615
|
+
this.settings.set({
|
|
15616
|
+
...this.settings(),
|
|
15617
|
+
...settings,
|
|
15618
|
+
});
|
|
15619
|
+
}
|
|
15620
|
+
const _ = effect(() => {
|
|
15621
|
+
const settings = this.settings();
|
|
15622
|
+
this._update(settings);
|
|
15623
|
+
}, ...(ngDevMode ? [{ debugName: "_" }] : []));
|
|
15624
|
+
}
|
|
15625
|
+
update(settings) {
|
|
15626
|
+
this.settings.set({ ...this.settings(), ...settings });
|
|
15627
|
+
}
|
|
15628
|
+
async _update(settings) {
|
|
15629
|
+
if (!this.map) {
|
|
15630
|
+
return;
|
|
15631
|
+
}
|
|
15632
|
+
const map = this.map;
|
|
15633
|
+
this.create();
|
|
15634
|
+
// Update paint/layout properties based on type
|
|
15635
|
+
switch (settings.type) {
|
|
15636
|
+
case 'circle':
|
|
15637
|
+
if (map.getLayer(this.CIRCLE_LAYER_ID)) {
|
|
15638
|
+
map.setLayoutProperty(this.CIRCLE_LAYER_ID, 'visibility', settings.visible ? 'visible' : 'none');
|
|
15639
|
+
map.setPaintProperty(this.CIRCLE_LAYER_ID, 'circle-radius', settings.radius);
|
|
15640
|
+
map.setPaintProperty(this.CIRCLE_LAYER_ID, 'circle-color', settings.color);
|
|
15641
|
+
map.setPaintProperty(this.CIRCLE_LAYER_ID, 'circle-opacity', settings.opacity);
|
|
15642
|
+
map.setPaintProperty(this.CIRCLE_LAYER_ID, 'circle-stroke-width', settings.strokeWidth);
|
|
15643
|
+
map.setPaintProperty(this.CIRCLE_LAYER_ID, 'circle-stroke-color', settings.strokeColor);
|
|
15644
|
+
}
|
|
15645
|
+
break;
|
|
15646
|
+
case 'icon':
|
|
15647
|
+
if (map.getLayer(this.ICON_LAYER_ID)) {
|
|
15648
|
+
await this.loadIcon();
|
|
15649
|
+
map.setLayoutProperty(this.ICON_LAYER_ID, 'visibility', settings.visible ? 'visible' : 'none');
|
|
15650
|
+
map.setLayoutProperty(this.ICON_LAYER_ID, 'icon-image', settings.iconName);
|
|
15651
|
+
map.setLayoutProperty(this.ICON_LAYER_ID, 'icon-size', settings.iconSize);
|
|
15652
|
+
map.setPaintProperty(this.ICON_LAYER_ID, 'icon-color', settings.color);
|
|
15653
|
+
map.setLayoutProperty(this.ICON_LAYER_ID, 'icon-allow-overlap', settings.iconAllowOverlap);
|
|
15654
|
+
}
|
|
15655
|
+
break;
|
|
15656
|
+
case 'heatmap':
|
|
15657
|
+
if (map.getLayer(this.HEATMAP_LAYER_ID)) {
|
|
15658
|
+
map.setLayoutProperty(this.HEATMAP_LAYER_ID, 'visibility', settings.visible ? 'visible' : 'none');
|
|
15659
|
+
map.setPaintProperty(this.HEATMAP_LAYER_ID, 'heatmap-radius', settings.radius);
|
|
15660
|
+
map.setPaintProperty(this.HEATMAP_LAYER_ID, 'heatmap-opacity', settings.opacity);
|
|
15661
|
+
}
|
|
15662
|
+
break;
|
|
15663
|
+
}
|
|
15664
|
+
}
|
|
15665
|
+
onReady(map, svc) {
|
|
15666
|
+
this.map = map;
|
|
15667
|
+
this.svc = svc;
|
|
15668
|
+
this.create();
|
|
15669
|
+
}
|
|
15670
|
+
reset() {
|
|
15671
|
+
this.count = 0;
|
|
15672
|
+
this.total = 0;
|
|
15673
|
+
this.legends = [];
|
|
15674
|
+
this.currentFilter = undefined;
|
|
15675
|
+
}
|
|
15676
|
+
clear() {
|
|
15677
|
+
if (!this.map) {
|
|
15678
|
+
return;
|
|
15679
|
+
}
|
|
15680
|
+
// Remove all layers for this instance
|
|
15681
|
+
RemoveLayer(this.map, this.CIRCLE_LAYER_ID);
|
|
15682
|
+
RemoveLayer(this.map, this.ICON_LAYER_ID);
|
|
15683
|
+
RemoveLayer(this.map, this.HEATMAP_LAYER_ID);
|
|
15684
|
+
this.map.off('click', this.CIRCLE_LAYER_ID, this.onClick);
|
|
15685
|
+
this.map.off('click', this.ICON_LAYER_ID, this.onClick);
|
|
15686
|
+
this.map.off('touchend', this.CIRCLE_LAYER_ID, this.onClick);
|
|
15687
|
+
this.map.off('touchend', this.ICON_LAYER_ID, this.onClick);
|
|
15688
|
+
this.count = 0;
|
|
15689
|
+
this.currentFilter = undefined;
|
|
15690
|
+
}
|
|
15691
|
+
updateLegends() { }
|
|
15692
|
+
// Method to create PMTiles layers
|
|
15693
|
+
create() {
|
|
15694
|
+
if (!this.map) {
|
|
15695
|
+
return;
|
|
15696
|
+
}
|
|
15697
|
+
const map = this.map;
|
|
15698
|
+
const settings = this.settings();
|
|
15699
|
+
// Add PMTiles source only if it doesn't exist (shared across instances)
|
|
15700
|
+
AddSource(map, this.SOURCE_ID, {
|
|
15701
|
+
type: 'vector',
|
|
15702
|
+
url: `pmtiles://${NaicsMapper.pmtilesUrl}`,
|
|
15703
|
+
});
|
|
15704
|
+
// Add visualization layer based on type
|
|
15705
|
+
this.addVisualizationLayer(map);
|
|
15706
|
+
// Add cluster layers if clustering is enabled
|
|
15707
|
+
// this.addClusterLayers(map);
|
|
15708
|
+
// Add popup on click
|
|
15709
|
+
map.on('click', this.CIRCLE_LAYER_ID, this.onClick);
|
|
15710
|
+
map.on('click', this.ICON_LAYER_ID, this.onClick);
|
|
15711
|
+
map.on('touchend', this.CIRCLE_LAYER_ID, this.onClick);
|
|
15712
|
+
map.on('touchend', this.ICON_LAYER_ID, this.onClick);
|
|
15713
|
+
}
|
|
15714
|
+
getActiveLayerId() {
|
|
15715
|
+
const settings = this.settings();
|
|
15716
|
+
switch (settings.type) {
|
|
15717
|
+
case 'circle':
|
|
15718
|
+
return this.CIRCLE_LAYER_ID;
|
|
15719
|
+
case 'icon':
|
|
15720
|
+
return this.ICON_LAYER_ID;
|
|
15721
|
+
case 'heatmap':
|
|
15722
|
+
return this.HEATMAP_LAYER_ID;
|
|
15723
|
+
default:
|
|
15724
|
+
return this.CIRCLE_LAYER_ID;
|
|
15725
|
+
}
|
|
15726
|
+
}
|
|
15727
|
+
async loadIcon() {
|
|
15728
|
+
if (!this.map) {
|
|
15729
|
+
return;
|
|
15730
|
+
}
|
|
15731
|
+
const map = this.map;
|
|
15732
|
+
const settings = this.settings();
|
|
15733
|
+
if (settings.iconUrl && !map.hasImage(settings.iconName)) {
|
|
15734
|
+
await mapboxloadImage(map, {
|
|
15735
|
+
name: settings.iconName,
|
|
15736
|
+
url: settings.iconUrl,
|
|
15737
|
+
sdf: settings.iconSdf,
|
|
15738
|
+
});
|
|
15739
|
+
}
|
|
15740
|
+
}
|
|
15741
|
+
async addVisualizationLayer(map) {
|
|
15742
|
+
const settings = this.settings();
|
|
15743
|
+
// Remove existing layers that ar not needed
|
|
15744
|
+
if (settings.type !== 'circle')
|
|
15745
|
+
RemoveLayer(map, this.CIRCLE_LAYER_ID);
|
|
15746
|
+
if (settings.type !== 'icon')
|
|
15747
|
+
RemoveLayer(map, this.ICON_LAYER_ID);
|
|
15748
|
+
if (settings.type !== 'heatmap')
|
|
15749
|
+
RemoveLayer(map, this.HEATMAP_LAYER_ID);
|
|
15750
|
+
// Add layer based on type
|
|
15751
|
+
switch (settings.type) {
|
|
15752
|
+
case 'circle':
|
|
15753
|
+
AddLayer(map, {
|
|
15754
|
+
id: this.CIRCLE_LAYER_ID,
|
|
15755
|
+
type: 'circle',
|
|
15756
|
+
source: this.SOURCE_ID,
|
|
15757
|
+
'source-layer': this.sourceLayer,
|
|
15758
|
+
layout: {
|
|
15759
|
+
visibility: settings.visible ? 'visible' : 'none',
|
|
15760
|
+
},
|
|
15761
|
+
paint: {
|
|
15762
|
+
'circle-radius': settings.radius,
|
|
15763
|
+
'circle-color': settings.color,
|
|
15764
|
+
'circle-opacity': settings.opacity,
|
|
15765
|
+
'circle-stroke-width': settings.strokeWidth,
|
|
15766
|
+
'circle-stroke-color': settings.strokeColor,
|
|
15767
|
+
},
|
|
15768
|
+
}, StandardLayersMapper.POINTS);
|
|
15769
|
+
break;
|
|
15770
|
+
case 'icon':
|
|
15771
|
+
// Load icon image if URL is provided and not already loaded
|
|
15772
|
+
await this.loadIcon();
|
|
15773
|
+
AddLayer(map, {
|
|
15774
|
+
id: this.ICON_LAYER_ID,
|
|
15775
|
+
type: 'symbol',
|
|
15776
|
+
source: this.SOURCE_ID,
|
|
15777
|
+
'source-layer': this.sourceLayer,
|
|
15778
|
+
layout: {
|
|
15779
|
+
visibility: settings.visible ? 'visible' : 'none',
|
|
15780
|
+
'icon-image': settings.iconName,
|
|
15781
|
+
'icon-size': settings.iconSize,
|
|
15782
|
+
'icon-allow-overlap': settings.iconAllowOverlap,
|
|
15783
|
+
},
|
|
15784
|
+
paint: {
|
|
15785
|
+
// Additional paint properties can be added here if needed
|
|
15786
|
+
'icon-color': settings.color,
|
|
15787
|
+
}
|
|
15788
|
+
}, StandardLayersMapper.POINTS);
|
|
15789
|
+
break;
|
|
15790
|
+
case 'heatmap':
|
|
15791
|
+
AddLayer(map, {
|
|
15792
|
+
id: this.HEATMAP_LAYER_ID,
|
|
15793
|
+
type: 'heatmap',
|
|
15794
|
+
source: this.SOURCE_ID,
|
|
15795
|
+
'source-layer': this.sourceLayer,
|
|
15796
|
+
layout: {
|
|
15797
|
+
visibility: settings.visible ? 'visible' : 'none',
|
|
15798
|
+
},
|
|
15799
|
+
paint: {
|
|
15800
|
+
'heatmap-weight': 1,
|
|
15801
|
+
'heatmap-intensity': 1,
|
|
15802
|
+
'heatmap-color': [
|
|
15803
|
+
'interpolate',
|
|
15804
|
+
['linear'],
|
|
15805
|
+
['heatmap-density'],
|
|
15806
|
+
0, 'rgba(0, 0, 255, 0)',
|
|
15807
|
+
0.1, 'royalblue',
|
|
15808
|
+
0.3, 'cyan',
|
|
15809
|
+
0.5, 'lime',
|
|
15810
|
+
0.7, 'yellow',
|
|
15811
|
+
1, 'red',
|
|
15812
|
+
],
|
|
15813
|
+
'heatmap-radius': settings.radius,
|
|
15814
|
+
'heatmap-opacity': settings.opacity,
|
|
15815
|
+
},
|
|
15816
|
+
}, StandardLayersMapper.POLYGONS_ACTIVE);
|
|
15817
|
+
break;
|
|
15818
|
+
}
|
|
15819
|
+
// Reapply filter if exists
|
|
15820
|
+
if (this.currentFilter) {
|
|
15821
|
+
this.filterByNaicsCode(map, this.currentFilter);
|
|
15822
|
+
}
|
|
15823
|
+
}
|
|
15824
|
+
// Method to filter by NAICS code (startsWith match)
|
|
15825
|
+
filterByNaicsCode(map, naicsCode) {
|
|
15826
|
+
this.currentFilter = naicsCode;
|
|
15827
|
+
const filter = naicsCode ? ['==', ['slice', ['get', 'NAICS_CODE'], 0, naicsCode.length], naicsCode] : null;
|
|
15828
|
+
const layerId = this.getActiveLayerId();
|
|
15829
|
+
if (map.getLayer(layerId)) {
|
|
15830
|
+
map.setFilter(layerId, filter);
|
|
15831
|
+
}
|
|
15832
|
+
}
|
|
15833
|
+
// Get current settings
|
|
15834
|
+
getSettings() {
|
|
15835
|
+
return { ...this.settings() };
|
|
15836
|
+
}
|
|
15837
|
+
onClick = (e) => {
|
|
15838
|
+
if (!this.map) {
|
|
15839
|
+
return;
|
|
15840
|
+
}
|
|
15841
|
+
const map = this.map;
|
|
15842
|
+
let features;
|
|
15843
|
+
const settings = this.settings();
|
|
15844
|
+
if (settings.type == 'circle') {
|
|
15845
|
+
features = this.map.queryRenderedFeatures(e.point, {
|
|
15846
|
+
layers: [this.CIRCLE_LAYER_ID],
|
|
15847
|
+
});
|
|
15848
|
+
}
|
|
15849
|
+
else if (settings.type == 'icon') {
|
|
15850
|
+
features = this.map.queryRenderedFeatures(e.point, {
|
|
15851
|
+
layers: [this.ICON_LAYER_ID],
|
|
15852
|
+
});
|
|
15853
|
+
}
|
|
15854
|
+
if (!features || features.length == 0) {
|
|
15855
|
+
return;
|
|
15856
|
+
}
|
|
15857
|
+
if (features.length > 0) {
|
|
15858
|
+
const item = features[0];
|
|
15859
|
+
if (item) {
|
|
15860
|
+
this.renderPopup(item).then((html) => {
|
|
15861
|
+
if (!html) {
|
|
15862
|
+
return;
|
|
15863
|
+
}
|
|
15864
|
+
new Popup().setLngLat(e.lngLat).setHTML(html).addTo(map);
|
|
15865
|
+
});
|
|
15866
|
+
}
|
|
15867
|
+
}
|
|
15868
|
+
};
|
|
15869
|
+
async renderPopup(f) {
|
|
15870
|
+
if (!f || !f.properties) {
|
|
15871
|
+
return undefined;
|
|
15872
|
+
}
|
|
15873
|
+
const item = f.properties;
|
|
15874
|
+
let html = `<b>${item['COMPANY_NAME'] || 'MISSING NAME'}</b><br>`;
|
|
15875
|
+
if (item?.['WEB_ADDRESS']) {
|
|
15876
|
+
let url = item['WEB_ADDRESS'].startsWith('http') ? item['WEB_ADDRESS'] : 'https://' + item['WEB_ADDRESS'];
|
|
15877
|
+
html += `<a href='${url}' target='_blank'>${url}</a><br />`;
|
|
15878
|
+
}
|
|
15879
|
+
if (item?.['ADDRESS']) {
|
|
15880
|
+
html += `${item?.['ADDRESS']}<br />`;
|
|
15881
|
+
}
|
|
15882
|
+
if (item?.['CITY'] && item?.['STATE']) {
|
|
15883
|
+
html += `${item?.['CITY']}, ${item?.['STATE']}<br />`;
|
|
15884
|
+
}
|
|
15885
|
+
if (item?.['PHONE']) {
|
|
15886
|
+
html += `${item?.['PHONE']}<br /><br />`;
|
|
15887
|
+
}
|
|
15888
|
+
if (item?.['SALES_VOLUME']) {
|
|
15889
|
+
html += `<b>Sales: </b>${item?.['SALES_VOLUME']}<br />`;
|
|
15890
|
+
}
|
|
15891
|
+
if (item?.['NUMBER_OF_EMPLOYEES']) {
|
|
15892
|
+
html += `<b>Employees: </b>${item?.['NUMBER_OF_EMPLOYEES']}<br />`;
|
|
15893
|
+
}
|
|
15894
|
+
if (item?.['NAICS_CODE']) {
|
|
15895
|
+
html += `<b>NAICS: </b>${item?.['NAICS_CODE']} ${item?.['NAICS_DESCRIPTION']} <br />`;
|
|
15896
|
+
}
|
|
15897
|
+
if (item?.['SIC_CODE1']) {
|
|
15898
|
+
html += `<b>SIC: </b>${item?.['SIC_CODE1']} ${item?.['SIC1_DESCRIPTION']}`;
|
|
15899
|
+
}
|
|
15900
|
+
return html;
|
|
15901
|
+
}
|
|
15902
|
+
}
|
|
15903
|
+
|
|
15614
15904
|
class SimpleMapper {
|
|
15615
15905
|
reset() {
|
|
15616
15906
|
if (this.map) {
|
|
@@ -15992,6 +16282,58 @@ class WatershedSettings {
|
|
|
15992
16282
|
autoSelectLayer = false;
|
|
15993
16283
|
}
|
|
15994
16284
|
|
|
16285
|
+
function isGeoloader(obj) {
|
|
16286
|
+
return typeof obj === 'object' &&
|
|
16287
|
+
obj !== null &&
|
|
16288
|
+
typeof obj.LoadBoundary === 'function';
|
|
16289
|
+
}
|
|
16290
|
+
function isMultiPolygon(obj) {
|
|
16291
|
+
return typeof obj === 'object' &&
|
|
16292
|
+
obj !== null &&
|
|
16293
|
+
obj.type === 'MultiPolygon';
|
|
16294
|
+
}
|
|
16295
|
+
function isPolygon(obj) {
|
|
16296
|
+
return typeof obj === 'object' &&
|
|
16297
|
+
obj !== null &&
|
|
16298
|
+
obj.type === 'Polygon';
|
|
16299
|
+
}
|
|
16300
|
+
function isNumber2DArray(input) {
|
|
16301
|
+
return Array.isArray(input) &&
|
|
16302
|
+
input.every(row => Array.isArray(row) &&
|
|
16303
|
+
row.every(cell => typeof cell === 'number'));
|
|
16304
|
+
}
|
|
16305
|
+
function isNumber3DArray(input) {
|
|
16306
|
+
return Array.isArray(input) &&
|
|
16307
|
+
input.every(matrix => Array.isArray(matrix) &&
|
|
16308
|
+
matrix.every(row => Array.isArray(row) &&
|
|
16309
|
+
row.every(cell => typeof cell === 'number')));
|
|
16310
|
+
}
|
|
16311
|
+
function toMultiPolygon(geom) {
|
|
16312
|
+
if (isMultiPolygon(geom)) {
|
|
16313
|
+
return geom;
|
|
16314
|
+
}
|
|
16315
|
+
if (isPolygon(geom)) {
|
|
16316
|
+
return {
|
|
16317
|
+
type: 'MultiPolygon',
|
|
16318
|
+
coordinates: [geom.coordinates]
|
|
16319
|
+
};
|
|
16320
|
+
}
|
|
16321
|
+
if (isNumber2DArray(geom)) {
|
|
16322
|
+
let raw = [geom];
|
|
16323
|
+
const coords = raw;
|
|
16324
|
+
return {
|
|
16325
|
+
type: 'MultiPolygon',
|
|
16326
|
+
coordinates: coords
|
|
16327
|
+
};
|
|
16328
|
+
}
|
|
16329
|
+
let raw = geom;
|
|
16330
|
+
const coords = raw;
|
|
16331
|
+
return {
|
|
16332
|
+
type: 'MultiPolygon',
|
|
16333
|
+
coordinates: coords
|
|
16334
|
+
};
|
|
16335
|
+
}
|
|
16336
|
+
|
|
15995
16337
|
class HttpBoundaryLoader {
|
|
15996
16338
|
static NewCustom(http, path) {
|
|
15997
16339
|
const loader = new HttpBoundaryLoader(http);
|
|
@@ -16096,5 +16438,5 @@ class HttpBoundaryLoader {
|
|
|
16096
16438
|
* Generated bundle index. Do not edit.
|
|
16097
16439
|
*/
|
|
16098
16440
|
|
|
16099
|
-
export { AddLayer, AddSource, AreaMapperMapper, BackgroundMaskMapper, BaseMapLight, BasemapSelect, BasemapSelectMenu, CensusTractMapper, CroplandDataLayerMapper, CroplandDataLayerSettings, CroplandLegend, DEFAULT_GLYPHS, DrawingMapper, EsriMapper, EsriSettings, HardinessMapper, HardinessSettings, HttpBoundaryLoader, MapAreaSelectComponent, MapComponent, MapSelectionService, MapService, MapStyles, MapboxMapperGroup, NAASMapper, NAASSettings, NoOpMapper, RemoveLayer, RemoveSource, SaveMap, SelectMode, SimpleMapper, StandardLayersMapper, Styles, VectorTileServerMapper, WatershedMapper, WatershedSettings, discoverLayers, isGeoloader, isMultiPolygon, isNumber2DArray, isNumber3DArray, isPolygon, mapboxLoadImages, mapboxloadImage, pmtilesPixelInfo, sampleTilesForLayers, simpleClone, toMultiPolygon, trySync };
|
|
16441
|
+
export { AddLayer, AddSource, AreaMapperMapper, BackgroundMaskMapper, BackgroundMaskSettings, BaseMapLight, BasemapSelect, BasemapSelectMenu, CensusTractMapper, CroplandDataLayerMapper, CroplandDataLayerSettings, CroplandLegend, DEFAULT_GLYPHS, DrawingMapper, EsriMapper, EsriSettings, HardinessMapper, HardinessSettings, HttpBoundaryLoader, MapAreaSelectComponent, MapComponent, MapSelectionService, MapService, MapStyles, MapboxMapperGroup, NAASMapper, NAASSettings, NaicsMapper, NaicsMapperSettings, NoOpMapper, RemoveLayer, RemoveSource, SaveMap, SelectMode, SimpleMapper, StandardLayersMapper, Styles, VectorTileServerMapper, WatershedMapper, WatershedSettings, discoverLayers, isGeoloader, isMultiPolygon, isNumber2DArray, isNumber3DArray, isPolygon, mapboxLoadImages, mapboxloadImage, pmtilesPixelInfo, sampleTilesForLayers, simpleClone, toMultiPolygon, trySync };
|
|
16100
16442
|
//# sourceMappingURL=foodmarketmaker-mapag.mjs.map
|