mapshaper 0.6.112 → 0.6.115
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/mapshaper.js +3236 -551
- package/package.json +6 -3
- package/www/basemap.js +6 -4
- package/www/elements.css +1 -1
- package/www/geopackage.js +4362 -0
- package/www/images/eye3.png +0 -0
- package/www/index.html +29 -10
- package/www/mapshaper-gui.js +304 -85
- package/www/mapshaper.js +3236 -551
- package/www/modules.js +147 -1
- package/www/page.css +71 -34
- package/www/sql-wasm.wasm +0 -0
package/www/mapshaper-gui.js
CHANGED
|
@@ -462,6 +462,16 @@
|
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
+
async function loadScript(src) {
|
|
466
|
+
return new Promise((resolve, reject) => {
|
|
467
|
+
const script = document.createElement('script');
|
|
468
|
+
script.src = src;
|
|
469
|
+
script.onload = () => resolve(script);
|
|
470
|
+
script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
|
|
471
|
+
document.head.appendChild(script);
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
|
|
465
475
|
var tagOrIdSelectorRE = /^#?[\w-]+$/;
|
|
466
476
|
|
|
467
477
|
El.__select = function(selector, root) {
|
|
@@ -655,9 +665,14 @@
|
|
|
655
665
|
},
|
|
656
666
|
|
|
657
667
|
show: function(css) {
|
|
658
|
-
var tag = this.el && this.el.tagName;
|
|
668
|
+
// var tag = this.el && this.el.tagName;
|
|
659
669
|
if (!this.visible()) {
|
|
660
|
-
|
|
670
|
+
// don't assume 'display:block'
|
|
671
|
+
this.el?.style.removeProperty('display');
|
|
672
|
+
if (this.computedStyle().display == 'none') {
|
|
673
|
+
this.css('display', 'block');
|
|
674
|
+
}
|
|
675
|
+
// this.css('display', tag == 'SPAN' ? 'inline-block' : 'block');
|
|
661
676
|
this._hidden = false;
|
|
662
677
|
}
|
|
663
678
|
return this;
|
|
@@ -666,13 +681,15 @@
|
|
|
666
681
|
html: function(html) {
|
|
667
682
|
if (arguments.length == 0) {
|
|
668
683
|
return this.el.innerHTML;
|
|
669
|
-
} else {
|
|
670
|
-
this.el.innerHTML = html;
|
|
671
|
-
return this;
|
|
672
684
|
}
|
|
685
|
+
this.el.innerHTML = html;
|
|
686
|
+
return this;
|
|
673
687
|
},
|
|
674
688
|
|
|
675
689
|
text: function(str) {
|
|
690
|
+
if (arguments.length == 0) {
|
|
691
|
+
return this.el.innerText;
|
|
692
|
+
}
|
|
676
693
|
this.html(utils$1.htmlEscape(str));
|
|
677
694
|
return this;
|
|
678
695
|
},
|
|
@@ -1927,6 +1944,18 @@
|
|
|
1927
1944
|
}
|
|
1928
1945
|
}
|
|
1929
1946
|
|
|
1947
|
+
var geopackagePromise = null;
|
|
1948
|
+
|
|
1949
|
+
async function loadGeopackageLib() {
|
|
1950
|
+
if (!window.modules || !window.modules['@ngageoint/geopackage']) {
|
|
1951
|
+
if (!geopackagePromise) {
|
|
1952
|
+
geopackagePromise = loadScript('geopackage.js');
|
|
1953
|
+
}
|
|
1954
|
+
await geopackagePromise;
|
|
1955
|
+
geopackagePromise = null;
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1930
1959
|
// @cb function(<FileList>)
|
|
1931
1960
|
function DropControl(gui, el, cb) {
|
|
1932
1961
|
var area = El(el);
|
|
@@ -1936,6 +1965,7 @@
|
|
|
1936
1965
|
.on('drop', ondrop)
|
|
1937
1966
|
.on('paste', onpaste);
|
|
1938
1967
|
area.node().addEventListener('paste', onpaste);
|
|
1968
|
+
// TODO: use same function for drop and paste
|
|
1939
1969
|
function ondrop(e) {
|
|
1940
1970
|
var files = e.dataTransfer.files;
|
|
1941
1971
|
var types = e.dataTransfer.types;
|
|
@@ -1946,7 +1976,7 @@
|
|
|
1946
1976
|
cb(e.dataTransfer.getData('text/uri-list').split(','));
|
|
1947
1977
|
} else if (types.includes('text/html')) {
|
|
1948
1978
|
// drag-dropping a highlighted link may pull in a chunk of html
|
|
1949
|
-
var urls = e.dataTransfer.getData('text/html')
|
|
1979
|
+
var urls = pastedHtmlToUrls(e.dataTransfer.getData('text/html'));
|
|
1950
1980
|
if (urls.length) {
|
|
1951
1981
|
cb(urls);
|
|
1952
1982
|
}
|
|
@@ -1955,7 +1985,7 @@
|
|
|
1955
1985
|
function onpaste(e) {
|
|
1956
1986
|
var types = Array.from(e.clipboardData.types || []).join(',');
|
|
1957
1987
|
var items = Array.from(e.clipboardData.items || []);
|
|
1958
|
-
var files;
|
|
1988
|
+
var files, str, urls;
|
|
1959
1989
|
if (GUI.textIsSelected()) {
|
|
1960
1990
|
// user is probably pasting text into an editable text field
|
|
1961
1991
|
return;
|
|
@@ -1971,12 +2001,22 @@
|
|
|
1971
2001
|
// formatted text can be available as both text/plain and text/html (e.g.
|
|
1972
2002
|
// a JSON data object copied from a GitHub issue).
|
|
1973
2003
|
//
|
|
2004
|
+
|
|
2005
|
+
// if html is present, it could be data (e.g. from Google Sheets) or a pasted link.
|
|
2006
|
+
// first we check for a link
|
|
2007
|
+
if (types.includes('text/html')) {
|
|
2008
|
+
urls = pastedHtmlToUrls(e.clipboardData.getData('text/html'));
|
|
2009
|
+
if (urls.length) {
|
|
2010
|
+
return cb(urls);
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
1974
2013
|
if (types.includes('text/plain')) {
|
|
1975
2014
|
// text from clipboard (supported by Chrome, FF, Safari)
|
|
1976
2015
|
// TODO: handle FF case of string containing multiple file names.
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
2016
|
+
str = e.clipboardData.getData('text/plain');
|
|
2017
|
+
urls = pastedTextToUrls(str);
|
|
2018
|
+
if (urls.length) {
|
|
2019
|
+
return cb(urls);
|
|
1980
2020
|
}
|
|
1981
2021
|
files = [pastedTextToFile(str)];
|
|
1982
2022
|
} else {
|
|
@@ -1998,6 +2038,21 @@
|
|
|
1998
2038
|
}
|
|
1999
2039
|
}
|
|
2000
2040
|
|
|
2041
|
+
function pastedHtmlToUrls(html) {
|
|
2042
|
+
var hrefRegex = /href\s*=\s*["']([^"']+)["']/gi;
|
|
2043
|
+
var matches = html.matchAll(hrefRegex);
|
|
2044
|
+
var urls = Array.from(matches, match => match[1]);
|
|
2045
|
+
return urls;
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
function pastedTextToUrls(str) {
|
|
2049
|
+
if (!looksLikeUrl(str)) return [];
|
|
2050
|
+
var regex = /https?:\/\/[^\s]+?(?=[\s,]|$)/g;
|
|
2051
|
+
var matches = str.matchAll(regex);
|
|
2052
|
+
var urls = Array.from(matches, match => match[0]);
|
|
2053
|
+
return urls;
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2001
2056
|
function pastedTextToFile(str) {
|
|
2002
2057
|
var type = internal.guessInputContentType(str);
|
|
2003
2058
|
var name;
|
|
@@ -2012,7 +2067,7 @@
|
|
|
2012
2067
|
return new File([blob], name);
|
|
2013
2068
|
}
|
|
2014
2069
|
|
|
2015
|
-
function
|
|
2070
|
+
function looksLikeUrl(str) {
|
|
2016
2071
|
return /^https?:\/\//.test(str);
|
|
2017
2072
|
}
|
|
2018
2073
|
|
|
@@ -2272,7 +2327,15 @@
|
|
|
2272
2327
|
}
|
|
2273
2328
|
|
|
2274
2329
|
async function importDataset(group, importOpts) {
|
|
2275
|
-
var dataset
|
|
2330
|
+
var dataset;
|
|
2331
|
+
if (group.gpkg) {
|
|
2332
|
+
await loadGeopackageLib();
|
|
2333
|
+
}
|
|
2334
|
+
if (group.gpkg || group.fgb) {
|
|
2335
|
+
dataset = await internal.importContentAsync(group, importOpts);
|
|
2336
|
+
} else {
|
|
2337
|
+
dataset = internal.importContent(group, importOpts);
|
|
2338
|
+
}
|
|
2276
2339
|
if (datasetIsEmpty(dataset)) return false;
|
|
2277
2340
|
if (group.layername) {
|
|
2278
2341
|
dataset.layers.forEach(lyr => lyr.name = group.layername);
|
|
@@ -2340,7 +2403,7 @@
|
|
|
2340
2403
|
function prepFilesForDownload(names) {
|
|
2341
2404
|
var items = names.map(function(name) {
|
|
2342
2405
|
var item = {name: name};
|
|
2343
|
-
if (
|
|
2406
|
+
if (looksLikeUrl(name)) {
|
|
2344
2407
|
item.url = name;
|
|
2345
2408
|
item.basename = GUI.getUrlFilename(name);
|
|
2346
2409
|
|
|
@@ -2459,6 +2522,8 @@
|
|
|
2459
2522
|
}
|
|
2460
2523
|
}
|
|
2461
2524
|
|
|
2525
|
+
// Group multiple files belonging to the same dataset together
|
|
2526
|
+
// (applies to Shapefiles)
|
|
2462
2527
|
function groupFilesForImport(data, importOpts) {
|
|
2463
2528
|
var names = importOpts.name ? [importOpts.name] : null;
|
|
2464
2529
|
if (initialImport && opts.name) { // name from mapshaper-gui --name option
|
|
@@ -4518,8 +4583,16 @@
|
|
|
4518
4583
|
async function exportMenuSelection(targets) {
|
|
4519
4584
|
// note: command line "target" option gets ignored
|
|
4520
4585
|
var opts = getExportOpts();
|
|
4586
|
+
if (opts.format == 'geopackage') {
|
|
4587
|
+
await loadGeopackageLib();
|
|
4588
|
+
}
|
|
4521
4589
|
opts.active_layer = gui.model.getActiveLayer().layer; // kludge to support restoring active layer in gui
|
|
4522
|
-
|
|
4590
|
+
try {
|
|
4591
|
+
var files = await internal.exportTargetLayers(model, targets, opts);
|
|
4592
|
+
} catch(e) {
|
|
4593
|
+
console.error(e);
|
|
4594
|
+
throw e;
|
|
4595
|
+
}
|
|
4523
4596
|
gui.session.layersExported(getTargetLayerIds(), getExportOptsAsString());
|
|
4524
4597
|
if (files.length == 1 && checkboxOn(clipboardCheckbox)) {
|
|
4525
4598
|
await saveFileContentToClipboard(files[0].content);
|
|
@@ -4641,7 +4714,7 @@
|
|
|
4641
4714
|
|
|
4642
4715
|
function getExportFormats() {
|
|
4643
4716
|
// return ['shapefile', 'geojson', 'topojson', 'json', 'dsv', 'kml', 'svg', internal.PACKAGE_EXT];
|
|
4644
|
-
return ['shapefile', 'json', 'geojson', 'dsv', 'topojson', 'kml', internal.PACKAGE_EXT, 'svg'];
|
|
4717
|
+
return ['shapefile', 'json', 'geojson', 'dsv', 'topojson', 'flatgeobuf', 'geopackage', 'kml', internal.PACKAGE_EXT, 'svg'];
|
|
4645
4718
|
}
|
|
4646
4719
|
|
|
4647
4720
|
function initFormatMenu() {
|
|
@@ -5297,7 +5370,7 @@
|
|
|
5297
5370
|
if (!lyr.data) {
|
|
5298
5371
|
missing.push('.dbf');
|
|
5299
5372
|
}
|
|
5300
|
-
if (!dataset.info.
|
|
5373
|
+
if (!dataset.info.wkt1 && !dataset.info.crs) {
|
|
5301
5374
|
missing.push('.prj');
|
|
5302
5375
|
}
|
|
5303
5376
|
}
|
|
@@ -6206,6 +6279,8 @@
|
|
|
6206
6279
|
throw new NonFatalError(formatLogArgs(arguments));
|
|
6207
6280
|
};
|
|
6208
6281
|
|
|
6282
|
+
var onceMessages = [];
|
|
6283
|
+
|
|
6209
6284
|
setLoggingForCLI();
|
|
6210
6285
|
|
|
6211
6286
|
function getLoggingSetter() {
|
|
@@ -6267,6 +6342,13 @@
|
|
|
6267
6342
|
_warn.apply(null, messageArgs(arguments));
|
|
6268
6343
|
}
|
|
6269
6344
|
|
|
6345
|
+
function warnOnce() {
|
|
6346
|
+
var str = formatLogArgs(arguments);
|
|
6347
|
+
if (onceMessages.includes(str)) return;
|
|
6348
|
+
onceMessages.push(str);
|
|
6349
|
+
_warn.apply(null, messageArgs(arguments));
|
|
6350
|
+
}
|
|
6351
|
+
|
|
6270
6352
|
// A way for the GUI to replace the CLI logging functions
|
|
6271
6353
|
function setLoggingFunctions(message, error, stop, warn) {
|
|
6272
6354
|
_message = message;
|
|
@@ -13548,12 +13630,18 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13548
13630
|
});
|
|
13549
13631
|
}
|
|
13550
13632
|
|
|
13551
|
-
|
|
13552
|
-
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
|
|
13633
|
+
var EMPTY_STYLE = {
|
|
13634
|
+
version: 8,
|
|
13635
|
+
sources: {},
|
|
13636
|
+
layers: []
|
|
13637
|
+
};
|
|
13638
|
+
|
|
13639
|
+
// function loadScript(url, cb) {
|
|
13640
|
+
// var script = document.createElement('script');
|
|
13641
|
+
// script.onload = cb;
|
|
13642
|
+
// script.src = url;
|
|
13643
|
+
// document.head.appendChild(script);
|
|
13644
|
+
// }
|
|
13557
13645
|
|
|
13558
13646
|
function loadStylesheet(url) {
|
|
13559
13647
|
var el = document.createElement('link');
|
|
@@ -13565,60 +13653,107 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13565
13653
|
}
|
|
13566
13654
|
|
|
13567
13655
|
function Basemap(gui) {
|
|
13568
|
-
var
|
|
13569
|
-
var
|
|
13570
|
-
var
|
|
13571
|
-
var
|
|
13656
|
+
var menuWrapper = gui.container.findChild('.display-options');
|
|
13657
|
+
var mainMenu = gui.container.findChild('.display-main-options');
|
|
13658
|
+
var addLayerMenu = gui.container.findChild('.add-basemap-menu').hide();
|
|
13659
|
+
var basemapList = gui.container.findChild('.added-basemaps');
|
|
13572
13660
|
var overlayButtons = gui.container.findChild('.basemap-overlay-buttons');
|
|
13573
13661
|
var container = gui.container.findChild('.basemap-container');
|
|
13574
13662
|
var basemapNote = gui.container.findChild('.basemap-note');
|
|
13575
|
-
var
|
|
13663
|
+
var addBasemap = gui.container.findChild('.add-basemap');
|
|
13664
|
+
var basemapWarning = gui.container.findChild('.basemap-warning').hide();
|
|
13576
13665
|
var mapEl = gui.container.findChild('.basemap');
|
|
13577
13666
|
var extentNote = El('div').addClass('basemap-prompt').appendTo(container).hide();
|
|
13578
13667
|
var params = window.mapboxParams;
|
|
13579
13668
|
var map;
|
|
13580
13669
|
var activeStyle;
|
|
13581
13670
|
var loading = false;
|
|
13582
|
-
var faded = false;
|
|
13671
|
+
// var faded = false;
|
|
13672
|
+
// var fadeBtn, clearBtn; // not in use
|
|
13673
|
+
var addBtn, addLayerBtn, cancelBtn;
|
|
13674
|
+
var customStyles = [];
|
|
13583
13675
|
|
|
13584
13676
|
if (params) {
|
|
13585
13677
|
// TODO: check page URL for compatibility with mapbox key
|
|
13586
13678
|
init();
|
|
13587
13679
|
} else {
|
|
13588
|
-
|
|
13680
|
+
menuWrapper.findChild('.basemap-opts').hide();
|
|
13589
13681
|
}
|
|
13590
13682
|
|
|
13591
13683
|
function init() {
|
|
13592
13684
|
gui.on('mode', function(e) {
|
|
13593
13685
|
if (e.prev == 'display_options') {
|
|
13594
|
-
|
|
13595
|
-
|
|
13686
|
+
// reset UI when leaving display options mode
|
|
13687
|
+
basemapWarning.hide();
|
|
13688
|
+
basemapNote.hide();
|
|
13689
|
+
// make sure secondary options menu gets closed
|
|
13690
|
+
mainMenu.show();
|
|
13691
|
+
addLayerMenu.hide();
|
|
13596
13692
|
}
|
|
13597
13693
|
if (e.name == 'display_options') {
|
|
13598
13694
|
onUpdate();
|
|
13599
13695
|
}
|
|
13600
13696
|
});
|
|
13601
13697
|
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13698
|
+
customStyles = GUI.getSavedValue('custom_basemaps') || [];
|
|
13699
|
+
updateBasemapList();
|
|
13700
|
+
|
|
13701
|
+
addBtn = new SimpleButton(menuWrapper.findChild('.add-btn'));
|
|
13702
|
+
addBtn.on('click', function(e) {
|
|
13703
|
+
addLayerMenu.show();
|
|
13704
|
+
mainMenu.hide();
|
|
13608
13705
|
});
|
|
13609
13706
|
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13707
|
+
addLayerBtn = new SimpleButton(menuWrapper.findChild('.add-layer-btn'));
|
|
13708
|
+
addLayerBtn.on('click', function(e) {
|
|
13709
|
+
var name = menuWrapper.findChild('.add-layer-name').el.value || 'Custom layer';
|
|
13710
|
+
var mapboxUrl = menuWrapper.findChild('.add-mapbox-url').el.value;
|
|
13711
|
+
var mapboxKey = menuWrapper.findChild('.add-mapbox-key')?.el?.value;
|
|
13712
|
+
var templateUrl = menuWrapper.findChild('.add-template-url').el.value;
|
|
13713
|
+
var style = {name};
|
|
13714
|
+
|
|
13715
|
+
if (mapboxUrl) {
|
|
13716
|
+
style.url = mapboxUrl;
|
|
13717
|
+
style.key = mapboxKey; // may be undefined
|
|
13718
|
+
style.type = 'mapbox';
|
|
13719
|
+
} else if (templateUrl) {
|
|
13720
|
+
style.url = templateUrl;
|
|
13721
|
+
style.type = menuWrapper.findChild('.tms').el.checked ? 'tms' : 'xyz';
|
|
13722
|
+
}
|
|
13723
|
+
|
|
13724
|
+
customStyles.push(style);
|
|
13725
|
+
updateBasemapList();
|
|
13726
|
+
showBasemap(style);
|
|
13727
|
+
addLayerMenu.hide();
|
|
13728
|
+
mainMenu.show();
|
|
13729
|
+
});
|
|
13730
|
+
|
|
13731
|
+
cancelBtn = new SimpleButton(menuWrapper.findChild('.add-cancel-btn'));
|
|
13732
|
+
cancelBtn.on('click', function() {
|
|
13733
|
+
addLayerMenu.hide();
|
|
13734
|
+
mainMenu.show();
|
|
13620
13735
|
});
|
|
13621
13736
|
|
|
13737
|
+
// fadeBtn = new SimpleButton(menuWrapper.findChild('.fade-btn'));
|
|
13738
|
+
// clearBtn = new SimpleButton(menuWrapper.findChild('.clear-btn'));
|
|
13739
|
+
// clearBtn.on('click', function() {
|
|
13740
|
+
// if (activeStyle) {
|
|
13741
|
+
// turnOffBasemap();
|
|
13742
|
+
// }
|
|
13743
|
+
// });
|
|
13744
|
+
|
|
13745
|
+
// fadeBtn.on('click', function() {
|
|
13746
|
+
// if (faded) {
|
|
13747
|
+
// mapEl.css('opacity', 1);
|
|
13748
|
+
// faded = false;
|
|
13749
|
+
// fadeBtn.text('Fade');
|
|
13750
|
+
// } else if (activeStyle) {
|
|
13751
|
+
// mapEl.css('opacity', 0.35);
|
|
13752
|
+
// faded = true;
|
|
13753
|
+
// fadeBtn.text('Unfade');
|
|
13754
|
+
// }
|
|
13755
|
+
// });
|
|
13756
|
+
|
|
13622
13757
|
gui.model.on('update', onUpdate);
|
|
13623
13758
|
|
|
13624
13759
|
gui.on('map_click', function() {
|
|
@@ -13627,10 +13762,10 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13627
13762
|
});
|
|
13628
13763
|
|
|
13629
13764
|
params.styles.forEach(function(style) {
|
|
13630
|
-
El('div')
|
|
13631
|
-
.html(`<div class="basemap-style-btn"><img src="${style.icon}"></img></div><div class="basemap-style-label">${style.name}</div>`)
|
|
13632
|
-
.appendTo(menuButtons)
|
|
13633
|
-
.findChild('.basemap-style-btn').on('click', onClick);
|
|
13765
|
+
// El('div')
|
|
13766
|
+
// .html(`<div class="basemap-style-btn"><img src="${style.icon}"></img></div><div class="basemap-style-label">${style.name}</div>`)
|
|
13767
|
+
// .appendTo(menuButtons)
|
|
13768
|
+
// .findChild('.basemap-style-btn').on('click', onClick);
|
|
13634
13769
|
|
|
13635
13770
|
El('div').addClass('basemap-overlay-btn basemap-style-btn')
|
|
13636
13771
|
.html(`<img src="${style.icon}"></img>`).on('click', onClick)
|
|
@@ -13644,7 +13779,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13644
13779
|
showBasemap(style);
|
|
13645
13780
|
}
|
|
13646
13781
|
updateButtons();
|
|
13647
|
-
// closeMenu();
|
|
13648
13782
|
}
|
|
13649
13783
|
});
|
|
13650
13784
|
}
|
|
@@ -13659,7 +13793,6 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13659
13793
|
function turnOffBasemap() {
|
|
13660
13794
|
activeStyle = null;
|
|
13661
13795
|
gui.map.setDisplayCRS(null);
|
|
13662
|
-
refresh();
|
|
13663
13796
|
}
|
|
13664
13797
|
|
|
13665
13798
|
function showBasemap(style) {
|
|
@@ -13668,20 +13801,98 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13668
13801
|
// Make sure that the selected layer style gets updated in gui-map.js
|
|
13669
13802
|
// gui.state.dark_basemap = style && style.dark || false;
|
|
13670
13803
|
if (map) {
|
|
13671
|
-
|
|
13804
|
+
setStyle(activeStyle);
|
|
13672
13805
|
refresh();
|
|
13673
13806
|
} else if (prepareMapView()) {
|
|
13674
13807
|
initMap();
|
|
13675
13808
|
}
|
|
13676
13809
|
}
|
|
13677
13810
|
|
|
13678
|
-
function
|
|
13679
|
-
|
|
13680
|
-
|
|
13811
|
+
function updateBasemapList() {
|
|
13812
|
+
var styles = params.styles.concat(customStyles);
|
|
13813
|
+
basemapList.empty();
|
|
13814
|
+
styles.forEach(function(style) {
|
|
13815
|
+
renderBasemapListItem(basemapList, style);
|
|
13816
|
+
});
|
|
13817
|
+
updateButtons();
|
|
13818
|
+
GUI.setSavedValue('custom_basemaps', customStyles);
|
|
13819
|
+
}
|
|
13820
|
+
|
|
13821
|
+
function isActiveStyle(style) {
|
|
13822
|
+
return style.url == activeStyle?.url;
|
|
13823
|
+
}
|
|
13824
|
+
|
|
13825
|
+
function renderBasemapListItem(parent, style) {
|
|
13826
|
+
var isCustomStyle = !!style.type;
|
|
13827
|
+
var el = El('div').html(`<div data-slug="${getStyleId(style)}" class="basemap-list-item"><img class="on-icon" src="images/eye3.png"><img class="off-icon" src="images/eye.png"> ${style.name} ${isCustomStyle ? '<img class="close-btn" draggable="false" src="images/close.png">' : ''}</div>`);
|
|
13828
|
+
el.appendTo(parent);
|
|
13829
|
+
el.findChild('.basemap-list-item').on('click', function() {
|
|
13830
|
+
if (isActiveStyle(style)) {
|
|
13831
|
+
turnOffBasemap();
|
|
13832
|
+
} else {
|
|
13833
|
+
showBasemap(style);
|
|
13834
|
+
}
|
|
13835
|
+
});
|
|
13836
|
+
|
|
13837
|
+
var closeBtn = el.findChild('.close-btn');
|
|
13838
|
+
closeBtn?.on('click', function(e) {
|
|
13839
|
+
e.stopPropagation();
|
|
13840
|
+
customStyles = customStyles.filter(function(o) {
|
|
13841
|
+
return o.url != style.url;
|
|
13842
|
+
});
|
|
13843
|
+
updateBasemapList();
|
|
13844
|
+
if (isActiveStyle(style)) {
|
|
13845
|
+
turnOffBasemap();
|
|
13846
|
+
}
|
|
13681
13847
|
});
|
|
13848
|
+
el.appendTo(parent);
|
|
13849
|
+
}
|
|
13850
|
+
|
|
13851
|
+
function getStyleId(style) {
|
|
13852
|
+
return ((style.name || '') + style.url).replace(/[^a-z0-9_]+/ig, '_');
|
|
13853
|
+
}
|
|
13854
|
+
|
|
13855
|
+
function setStyle(style) {
|
|
13856
|
+
// update mapbox access token (user-defined styles may have a different key)
|
|
13857
|
+
window.mapboxgl.accessToken = style.key || (window.location.hostname == 'localhost' ?
|
|
13858
|
+
params.localhost_key : params.production_key) || params.key;
|
|
13859
|
+
|
|
13860
|
+
if (style.type == 'mapbox' || !style.type) {
|
|
13861
|
+
map.setStyle(style.url);
|
|
13862
|
+
} else if (style.type == 'xyz' || style.type == 'tms') {
|
|
13863
|
+
map.setStyle({
|
|
13864
|
+
'version': 8,
|
|
13865
|
+
'sources': {
|
|
13866
|
+
'raster-tiles': {
|
|
13867
|
+
'type': 'raster',
|
|
13868
|
+
'tiles': [style.url],
|
|
13869
|
+
'scheme': style.type, // xyz or tms
|
|
13870
|
+
'tileSize': 256, // style.url.includes('@2x') ? 512 : 256
|
|
13871
|
+
}
|
|
13872
|
+
},
|
|
13873
|
+
'layers': [
|
|
13874
|
+
{
|
|
13875
|
+
'id': getStyleId(style),
|
|
13876
|
+
'type': 'raster',
|
|
13877
|
+
'source': 'raster-tiles',
|
|
13878
|
+
'minzoom': 0
|
|
13879
|
+
// 'maxzoom': 22
|
|
13880
|
+
}
|
|
13881
|
+
]
|
|
13882
|
+
});
|
|
13883
|
+
} else {
|
|
13884
|
+
error$1('unsupported map style:', style);
|
|
13885
|
+
}
|
|
13886
|
+
}
|
|
13887
|
+
|
|
13888
|
+
function updateButtons() {
|
|
13682
13889
|
overlayButtons.findChildren('.basemap-style-btn').forEach(function(el, i) {
|
|
13683
13890
|
el.classed('active', params.styles[i] == activeStyle);
|
|
13684
13891
|
});
|
|
13892
|
+
|
|
13893
|
+
menuWrapper.findChildren('.basemap-list-item').forEach(function(el, i) {
|
|
13894
|
+
el.classed('active', el.node().getAttribute('data-slug') == (activeStyle ? getStyleId(activeStyle) : ''));
|
|
13895
|
+
});
|
|
13685
13896
|
}
|
|
13686
13897
|
|
|
13687
13898
|
function onUpdate() {
|
|
@@ -13689,16 +13900,18 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13689
13900
|
var info = getDatasetCrsInfo(activeLyr?.dataset); // defaults to wgs84
|
|
13690
13901
|
var dataCRS = info.crs || null;
|
|
13691
13902
|
var displayCRS = gui.map.getDisplayCRS();
|
|
13903
|
+
var basemapsNotAvailable = !dataCRS || !displayCRS || !crsIsUsable(displayCRS) || !crsIsUsable(dataCRS);
|
|
13692
13904
|
var warning, note;
|
|
13693
13905
|
|
|
13694
|
-
|
|
13695
|
-
if (!dataCRS || !displayCRS || !crsIsUsable(displayCRS) || !crsIsUsable(dataCRS)) {
|
|
13906
|
+
if (basemapsNotAvailable) {
|
|
13696
13907
|
warning = 'This data is incompatible with the basemaps.';
|
|
13697
|
-
if (!internal.layerHasGeometry(activeLyr.layer)) {
|
|
13908
|
+
if (activeLyr && !internal.layerHasGeometry(activeLyr.layer)) {
|
|
13698
13909
|
warning += ' Reason: layer is missing geographic data';
|
|
13699
13910
|
} else if (!dataCRS) {
|
|
13700
13911
|
warning += ' Reason: unknown projection.';
|
|
13701
13912
|
}
|
|
13913
|
+
basemapList.hide();
|
|
13914
|
+
addBasemap.hide();
|
|
13702
13915
|
basemapWarning.html(warning).show();
|
|
13703
13916
|
basemapNote.hide();
|
|
13704
13917
|
overlayButtons.addClass('disabled');
|
|
@@ -13708,6 +13921,8 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13708
13921
|
note = `Note: basemaps use the Mercator projection.`;
|
|
13709
13922
|
basemapNote.text(note).show();
|
|
13710
13923
|
overlayButtons.show();
|
|
13924
|
+
basemapList.show();
|
|
13925
|
+
addBasemap.show();
|
|
13711
13926
|
overlayButtons.removeClass('disabled');
|
|
13712
13927
|
}
|
|
13713
13928
|
}
|
|
@@ -13734,32 +13949,33 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13734
13949
|
return bbox2;
|
|
13735
13950
|
}
|
|
13736
13951
|
|
|
13737
|
-
function initMap() {
|
|
13738
|
-
var accessToken = (window.location.hostname == 'localhost' ?
|
|
13739
|
-
|
|
13952
|
+
async function initMap() {
|
|
13953
|
+
// var accessToken = (window.location.hostname == 'localhost' ?
|
|
13954
|
+
// params.localhost_key : params.production_key) || params.key;
|
|
13740
13955
|
if (!enabled() || map || loading) return;
|
|
13741
13956
|
loading = true;
|
|
13742
13957
|
loadStylesheet(params.css);
|
|
13743
|
-
loadScript(params.js
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
|
|
13757
|
-
|
|
13758
|
-
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
|
|
13762
|
-
|
|
13958
|
+
await loadScript(params.js);
|
|
13959
|
+
map = new window.mapboxgl.Map({
|
|
13960
|
+
logoPosition: 'bottom-left',
|
|
13961
|
+
container: mapEl.node(),
|
|
13962
|
+
// style: activeStyle.url,
|
|
13963
|
+
style: EMPTY_STYLE, // initializing with empty style to support custom styles
|
|
13964
|
+
bounds: getLonLatBounds(),
|
|
13965
|
+
doubleClickZoom: false,
|
|
13966
|
+
dragPan: false,
|
|
13967
|
+
dragRotate: false,
|
|
13968
|
+
scrollZoom: false,
|
|
13969
|
+
interactive: false,
|
|
13970
|
+
keyboard: false,
|
|
13971
|
+
maxPitch: 0,
|
|
13972
|
+
projection: 'mercator', // prevent globe view when zoomed out
|
|
13973
|
+
renderWorldCopies: true // false // false prevents panning off the map
|
|
13974
|
+
});
|
|
13975
|
+
setStyle(activeStyle);
|
|
13976
|
+
map.on('load', function() {
|
|
13977
|
+
loading = false;
|
|
13978
|
+
refresh();
|
|
13763
13979
|
});
|
|
13764
13980
|
}
|
|
13765
13981
|
|
|
@@ -13804,8 +14020,11 @@ GUI and setting the size and crop of SVG output.</p><div><input type="text" clas
|
|
|
13804
14020
|
function refresh() {
|
|
13805
14021
|
var off = !enabled() || !map || loading || !activeStyle ||
|
|
13806
14022
|
!gui.map.getDisplayCRS(); // may be slow if getting bounds of many shapes
|
|
13807
|
-
fadeBtn.active(!off);
|
|
13808
|
-
clearBtn.active(!off);
|
|
14023
|
+
// fadeBtn.active(!off);
|
|
14024
|
+
// clearBtn.active(!off);
|
|
14025
|
+
|
|
14026
|
+
updateButtons();
|
|
14027
|
+
|
|
13809
14028
|
if (off) {
|
|
13810
14029
|
hide();
|
|
13811
14030
|
extentNote.hide();
|