mapshaper 0.5.96 → 0.5.99

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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ v0.5.99
2
+ * Added support for viewing data against a Mapbox basemap (enabled on the mapshaper.org site).
3
+
4
+ v0.5.98
5
+ * Better handling of null data by the -classify command.
6
+
7
+ v0.5.97
8
+ * Better warnings and error messages.
9
+
1
10
  v0.5.96
2
11
  * Added colors=random option to the -classify command.
3
12
  * Added more sensible default behavior to the -classify command.
package/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.95";
3
+ var VERSION = "0.5.96";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -1771,6 +1771,8 @@
1771
1771
  // avoid re-allocating memory
1772
1772
  var xx2 = new Float64Array(data.xx.buffer, 0, n-1);
1773
1773
  var yy2 = new Float64Array(data.yy.buffer, 0, n-1);
1774
+ var zz2 = arcs.isFlat() ? null : new Float64Array(data.zz.buffer, 0, n-1);
1775
+ var z = arcs.getRetainedInterval();
1774
1776
  var count = 0;
1775
1777
  var found = false;
1776
1778
  for (var j=0; j<nn.length; j++) {
@@ -1784,24 +1786,31 @@
1784
1786
  utils.copyElements(data.yy, 0, yy2, 0, i);
1785
1787
  utils.copyElements(data.xx, i+1, xx2, i, n-i-1);
1786
1788
  utils.copyElements(data.yy, i+1, yy2, i, n-i-1);
1787
- arcs.updateVertexData(nn, xx2, yy2, null);
1789
+ if (zz2) {
1790
+ utils.copyElements(data.zz, 0, zz2, 0, i);
1791
+ utils.copyElements(data.zz, i+1, zz2, i, n-i-1);
1792
+ }
1793
+ arcs.updateVertexData(nn, xx2, yy2, zz2);
1794
+ arcs.setRetainedInterval(z);
1788
1795
  }
1789
1796
 
1790
1797
  function insertVertex(arcs, i, p) {
1791
- // TODO: add extra bytes to the buffers, to reduce new memory allocation
1792
1798
  var data = arcs.getVertexData();
1793
1799
  var nn = data.nn;
1794
1800
  var n = data.xx.length;
1795
1801
  var count = 0;
1796
1802
  var found = false;
1797
- var xx2, yy2;
1803
+ var xx2, yy2, zz2;
1798
1804
  // avoid re-allocating memory on each insertion
1799
1805
  if (data.xx.buffer.byteLength >= data.xx.length * 8 + 8) {
1800
1806
  xx2 = new Float64Array(data.xx.buffer, 0, n+1);
1801
1807
  yy2 = new Float64Array(data.yy.buffer, 0, n+1);
1802
1808
  } else {
1803
- xx2 = new Float64Array(new ArrayBuffer((n + 20) * 8), 0, n+1);
1804
- yy2 = new Float64Array(new ArrayBuffer((n + 20) * 8), 0, n+1);
1809
+ xx2 = new Float64Array(new ArrayBuffer((n + 50) * 8), 0, n+1);
1810
+ yy2 = new Float64Array(new ArrayBuffer((n + 50) * 8), 0, n+1);
1811
+ }
1812
+ if (!arcs.isFlat()) {
1813
+ zz2 = new Float64Array(new ArrayBuffer((n + 1) * 8), 0, n+1);
1805
1814
  }
1806
1815
  for (var j=0; j<nn.length; j++) {
1807
1816
  count += nn[j];
@@ -1816,7 +1825,12 @@
1816
1825
  utils.copyElements(data.yy, i, yy2, i+1, n-i);
1817
1826
  xx2[i] = p[0];
1818
1827
  yy2[i] = p[1];
1819
- arcs.updateVertexData(nn, xx2, yy2, null);
1828
+ if (zz2) {
1829
+ zz2[i] = Infinity;
1830
+ utils.copyElements(data.zz, 0, zz2, 0, i);
1831
+ utils.copyElements(data.zz, i, zz2, i+1, n-i);
1832
+ }
1833
+ arcs.updateVertexData(nn, xx2, yy2, zz2);
1820
1834
  }
1821
1835
 
1822
1836
  var ArcUtils = /*#__PURE__*/Object.freeze({
@@ -4663,8 +4677,8 @@
4663
4677
  if (isLatLngCRS(P)) {
4664
4678
  return xy.concat();
4665
4679
  }
4666
- proj = getProjInfo(P, getCRS('wgs84'));
4667
- return proj(xy);
4680
+ proj = getProjTransform(P, getCRS('wgs84'));
4681
+ return proj(xy[0], xy[1]);
4668
4682
  }
4669
4683
 
4670
4684
  function getProjInfo(dataset) {
@@ -4810,6 +4824,21 @@
4810
4824
  return P && P.is_latlong || false;
4811
4825
  }
4812
4826
 
4827
+ function isWGS84(P) {
4828
+ if (!isLatLngCRS(P)) return false;
4829
+ var proj4 = crsToProj4(P);
4830
+ return proj4.toLowerCase().includes('84');
4831
+ }
4832
+
4833
+ function isWebMercator(P) {
4834
+ if (!P) return false;
4835
+ var str = crsToProj4(P);
4836
+ // e.g. +proj=merc +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +wktext +a=6378137 +b=6378137 +nadgrids=@null
4837
+ // e.g. +proj=merc +a=6378137 +b=6378137
4838
+ // TODO: support https://proj.org/operations/projections/webmerc.html
4839
+ return str.includes('+proj=merc') && str.includes('+a=6378137') && str.includes('+b=6378137');
4840
+ }
4841
+
4813
4842
  function isLatLngDataset(dataset) {
4814
4843
  return isLatLngCRS(getDatasetCRS(dataset));
4815
4844
  }
@@ -4864,6 +4893,8 @@
4864
4893
  getScaleFactorAtXY: getScaleFactorAtXY,
4865
4894
  isProjectedCRS: isProjectedCRS,
4866
4895
  isLatLngCRS: isLatLngCRS,
4896
+ isWGS84: isWGS84,
4897
+ isWebMercator: isWebMercator,
4867
4898
  isLatLngDataset: isLatLngDataset,
4868
4899
  printProjections: printProjections,
4869
4900
  translatePrj: translatePrj,
@@ -8357,8 +8388,8 @@
8357
8388
  }
8358
8389
 
8359
8390
  function getBoundsPrecisionForDisplay(bbox) {
8360
- var w = bbox[2] - bbox[0],
8361
- h = bbox[3] - bbox[1],
8391
+ var w = Math.abs(bbox[2] - bbox[0]),
8392
+ h = Math.abs(bbox[3] - bbox[1]),
8362
8393
  range = Math.min(w, h) + 1e-8,
8363
8394
  digits = 0;
8364
8395
  while (range < 2000) {
@@ -8877,12 +8908,24 @@
8877
8908
  arg = arg ? String(arg) : '';
8878
8909
  var hexStr = hexRxp.test(arg) ? arg : lookupColorName(arg);
8879
8910
  var rgb = null;
8880
- if (hexStr) rgb = parseHexColor(hexStr);
8881
- else if (rgbaRxp.test(arg)) rgb = parseRGBA(arg);
8882
- if (!testRGB(rgb)) stop("Unsupported color:", arg);
8911
+ if (hexStr) {
8912
+ rgb = parseHexColor(hexStr);
8913
+ } else if (rgbaRxp.test(arg)) {
8914
+ rgb = parseRGBA(arg);
8915
+ }
8916
+ if (rgb && !testRGB(rgb)) {
8917
+ rgb = null;
8918
+ }
8883
8919
  return rgb;
8884
8920
  }
8885
8921
 
8922
+ function validateColor(arg) {
8923
+ if (!parseColor(arg)) {
8924
+ stop("Unsupported color:", arg);
8925
+ }
8926
+ return true;
8927
+ }
8928
+
8886
8929
  function testRGB(o) {
8887
8930
  return !!o && testChannel(o.r) && testChannel(o.g) && testChannel(o.b) &&
8888
8931
  testAlpha(o.a);
@@ -9028,7 +9071,7 @@
9028
9071
  weights = normalizeWeights(weights);
9029
9072
  if (!weights) return '#eee';
9030
9073
  var blended = colors.reduce(function(memo, col, i) {
9031
- var rgb = parseColor(col);
9074
+ var rgb = validateColor(col) && parseColor(col);
9032
9075
  var w = +weights[i] || 0;
9033
9076
  memo.r += rgb.r * w;
9034
9077
  memo.g += rgb.g * w;
@@ -28870,7 +28913,8 @@ ${svg}
28870
28913
  categorical: [],
28871
28914
  sequential: [],
28872
28915
  rainbow: [],
28873
- diverging: []
28916
+ diverging: [],
28917
+ all: []
28874
28918
  };
28875
28919
  var ramps;
28876
28920
 
@@ -28890,6 +28934,19 @@ ${svg}
28890
28934
  '3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9');
28891
28935
  addCategoricalScheme('Tableau20',
28892
28936
  '4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5');
28937
+ index.all = [].concat(index.sequential, index.rainbow, index.diverging, index.categorical);
28938
+
28939
+ }
28940
+
28941
+ function standardName(name) {
28942
+ if (!name) return null;
28943
+ var lcname = name.toLowerCase();
28944
+ for (var i=0; i<index.all.length; i++) {
28945
+ if (index.all[i].toLowerCase() == lcname) {
28946
+ return index.all[i];
28947
+ }
28948
+ }
28949
+ return null;
28893
28950
  }
28894
28951
 
28895
28952
  function addSchemesFromD3(type, names) {
@@ -28944,9 +29001,26 @@ ${svg}
28944
29001
  print ('\nMulti-hue/rainbow\n' + formatStringsAsGrid(index.rainbow));
28945
29002
  }
28946
29003
 
29004
+ function pickRandomColorScheme(type) {
29005
+ initSchemes();
29006
+ var names = index[type];
29007
+ if (!names) error('Unknown color scheme type:', type);
29008
+ var i = Math.floor(Math.random() * names.length);
29009
+ return names[i];
29010
+ }
29011
+
29012
+ function getRandomColors(n) {
29013
+ initSchemes();
29014
+ var colors = getCategoricalColorScheme('Tableau20', 20);
29015
+ utils.shuffle(colors);
29016
+ colors = wrapColors(colors, n);
29017
+ return colors.slice(0, n);
29018
+ }
29019
+
28947
29020
  function getCategoricalColorScheme(name, n) {
28948
29021
  var colors;
28949
29022
  initSchemes();
29023
+ name = standardName(name);
28950
29024
  if (!isColorSchemeName(name)) {
28951
29025
  stop('Unknown color scheme name:', name);
28952
29026
  } else if (isCategoricalColorScheme(name)) {
@@ -28973,17 +29047,17 @@ ${svg}
28973
29047
 
28974
29048
  function isColorSchemeName(name) {
28975
29049
  initSchemes();
28976
- return index.categorical.includes(name) || index.sequential.includes(name) ||
28977
- index.diverging.includes(name) || index.rainbow.includes(name);
29050
+ return index.all.includes(standardName(name));
28978
29051
  }
28979
29052
 
28980
29053
  function isCategoricalColorScheme(name) {
28981
29054
  initSchemes();
28982
- return index.categorical.includes(name);
29055
+ return index.categorical.includes(standardName(name));
28983
29056
  }
28984
29057
 
28985
29058
  function getColorRamp(name, n, stops) {
28986
29059
  initSchemes();
29060
+ name = standardName(name);
28987
29061
  var lib = require('d3-scale-chromatic');
28988
29062
  var ramps = lib['scheme' + name];
28989
29063
  var interpolate = lib['interpolate' + name];
@@ -29016,47 +29090,68 @@ ${svg}
29016
29090
  return ramp;
29017
29091
  }
29018
29092
 
29093
+ function getNullValue(opts) {
29094
+ var nullValue;
29095
+ if ('null_value' in opts) {
29096
+ nullValue = parseNullValue(opts.null_value);
29097
+ } else if (opts.colors) {
29098
+ nullValue = '#eee';
29099
+ } else if (opts.values) {
29100
+ nullValue = null;
29101
+ } else {
29102
+ nullValue = -1; // kludge, to match behavior of getClassValues()
29103
+ }
29104
+ return nullValue;
29105
+ }
29106
+
29107
+ // Parse command line string arguments to the correct data type
29108
+ function parseNullValue(val) {
29109
+ if (utils.isString(val) && !isNaN(+val)) {
29110
+ val = +val;
29111
+ }
29112
+ if (val === 'null') {
29113
+ val = null;
29114
+ }
29115
+ return val;
29116
+ }
29117
+
29019
29118
  function getClassValues(method, n, opts) {
29020
29119
  var categorical = method == 'categorical' || method == 'non-adjacent';
29021
- var colorArg = opts.colors ? opts.colors[0] : null;
29120
+ var colorArg = opts.colors && opts.colors.length == 1 ? opts.colors[0] : null;
29022
29121
  var colorScheme;
29023
29122
 
29024
- if (isColorSchemeName(colorArg)) {
29123
+ if (colorArg == 'random') {
29124
+ if (categorical) {
29125
+ return getRandomColors(n);
29126
+ }
29127
+ colorScheme = pickRandomColorScheme('sequential');
29128
+ message('Randomly selected color ramp:', colorScheme);
29129
+ } else if (isColorSchemeName(colorArg)) {
29025
29130
  colorScheme = colorArg;
29026
- } else if (colorArg == 'random') {
29027
- colorScheme = categorical ? 'Tableau20' : 'BuGn'; // TODO: randomize
29131
+ } else if (colorArg && !parseColor(colorArg)) {
29132
+ stop('Unrecognized color scheme name:', colorArg);
29028
29133
  } else if (opts.colors) {
29029
- // validate colors
29030
- opts.colors.forEach(parseColor);
29134
+ opts.colors.forEach(validateColor);
29031
29135
  }
29032
29136
 
29033
- if (categorical) {
29034
- if (colorScheme && isCategoricalColorScheme(colorScheme)) {
29137
+ if (colorScheme) {
29138
+ if (categorical && isCategoricalColorScheme(colorScheme)) {
29035
29139
  return getCategoricalColorScheme(colorScheme, n);
29036
- } else if (colorScheme) {
29037
- // assume we have a sequential ramp
29140
+ } else {
29038
29141
  return getColorRamp(colorScheme, n, opts.stops);
29039
- } else if (opts.colors || opts.values) {
29142
+ }
29143
+ } else if (opts.colors || opts.values) {
29144
+ if (categorical) {
29040
29145
  return getCategoricalValues(opts.colors || opts.values, n);
29041
29146
  } else {
29042
- // numerical indexes seem to make sense for non-adjacent and categorical colors
29043
- return getIndexes(n);
29044
- }
29045
- } else {
29046
- // sequential values
29047
- if (colorScheme) {
29048
- return getColorRamp(colorScheme, n, opts.stops);
29049
- } else if (opts.colors || opts.values) {
29050
29147
  return getInterpolableValues(opts.colors || opts.values, n, opts);
29051
- } else {
29052
- // TODO: rethink this
29053
- // return getInterpolableValues([0, 1], n, opts);
29054
- return getIndexes(n);
29055
29148
  }
29149
+ } else {
29150
+ // use numerical class indexes (0, 1, ...) if no values are given
29151
+ return getIndexes(n);
29056
29152
  }
29057
29153
  }
29058
29154
 
29059
-
29060
29155
  function getCategoricalValues(values, n) {
29061
29156
  if (n != values.length) {
29062
29157
  stop('Mismatch in number of categories and number of values');
@@ -29093,26 +29188,36 @@ ${svg}
29093
29188
  return values;
29094
29189
  }
29095
29190
 
29096
- var sequential = ['quantile', 'nice', 'equal-interval', 'hybrid'];
29191
+ var sequential = ['quantile', 'nice', 'equal-interval', 'hybrid', 'breaks'];
29097
29192
  var all = ['non-adjacent', 'indexed', 'categorical'].concat(sequential);
29098
29193
 
29099
- function getClassifyMethod(opts, dataFieldType) {
29194
+ function getClassifyMethod(opts, dataType) {
29100
29195
  var method;
29101
29196
  if (opts.method) {
29102
29197
  method = opts.method;
29198
+ } else if (opts.breaks) {
29199
+ method = 'breaks';
29103
29200
  } else if (opts.index_field) {
29104
29201
  method = 'indexed';
29105
- } else if (opts.categories || dataFieldType == 'string') {
29202
+ } else if (opts.categories || dataType == 'string') {
29106
29203
  method = 'categorical';
29107
- } else if (dataFieldType == 'number') {
29204
+ } else if (dataType == 'number') {
29108
29205
  method = 'quantile'; // TODO: validate data field
29206
+ } else if (dataType == 'date' || dataType == 'object') {
29207
+ stop('Data type does not support classification:', dataType);
29208
+ } else if (dataType === null) {
29209
+ // data field is empty
29210
+ return null; // kludge
29211
+ } else if (dataType === undefined) {
29212
+ // no data field was given
29213
+ stop('Expected a data field to classify or the non-adjacent option');
29109
29214
  } else {
29110
29215
  stop('Unable to determine which classification method to use.');
29111
29216
  }
29112
29217
  if (!all.includes(method)) {
29113
29218
  stop('Not a recognized classification method:', method);
29114
29219
  }
29115
- if (sequential.includes(method) && dataFieldType != 'number') {
29220
+ if (sequential.includes(method) && dataType != 'number' && dataType !== null) {
29116
29221
  stop('The', method, 'method requires a numerical data field');
29117
29222
  }
29118
29223
  return method;
@@ -29125,7 +29230,7 @@ ${svg}
29125
29230
  var opts = optsArg || {};
29126
29231
  var records = lyr.data && lyr.data.getRecords();
29127
29232
  var valuesAreColors = !!opts.colors;
29128
- var dataField, dataFieldType, outputField;
29233
+ var dataField, fieldType, outputField;
29129
29234
  var values, nullValue;
29130
29235
  var classifyByValue, classifyByRecordId;
29131
29236
  var numClasses, numValues;
@@ -29139,9 +29244,10 @@ ${svg}
29139
29244
  //
29140
29245
  if (opts.index_field) {
29141
29246
  dataField = opts.index_field;
29142
- } else if (opts.field) {
29247
+ fieldType = getColumnType(opts.field, records);
29248
+ } else if (opts.field) {
29143
29249
  dataField = opts.field;
29144
- dataFieldType = getColumnType(opts.field, records);
29250
+ fieldType = getColumnType(opts.field, records);
29145
29251
  }
29146
29252
  if (dataField) {
29147
29253
  requireDataField(lyr.data, dataField);
@@ -29149,7 +29255,7 @@ ${svg}
29149
29255
 
29150
29256
  // get classification method
29151
29257
  //
29152
- method = getClassifyMethod(opts, dataFieldType);
29258
+ method = getClassifyMethod(opts, fieldType);
29153
29259
 
29154
29260
  // validate classification method
29155
29261
  if (method == 'non-adjacent') {
@@ -29167,6 +29273,7 @@ ${svg}
29167
29273
  // get the number of classes and the number of values
29168
29274
  //
29169
29275
  // expand categories if value is '*'
29276
+ // use all unique values if categories option is missing
29170
29277
  if (method == 'categorical') {
29171
29278
  if ((!opts.categories || opts.categories.includes('*')) && dataField) {
29172
29279
  opts.categories = getUniqFieldValues(records, dataField);
@@ -29208,24 +29315,16 @@ ${svg}
29208
29315
  message('Colors:', formatValuesForLogging(values));
29209
29316
  }
29210
29317
 
29211
- // get null value
29212
- //
29213
- if ('null_value' in opts) {
29214
- nullValue = opts.null_value;
29215
- } else if (valuesAreColors) {
29216
- nullValue = '#eee';
29217
- } else if (opts.values) {
29218
- nullValue = null;
29219
- } else {
29220
- nullValue = -1; // kludge, to match behavior of getClassValues()
29221
- }
29222
-
29318
+ nullValue = getNullValue(opts);
29223
29319
 
29224
29320
  // get a function to convert input data to class indexes
29225
29321
  //
29226
- if (method == 'non-adjacent') {
29322
+ if (fieldType === null) {
29323
+ // no valid data -- always return null value
29324
+ classifyByRecordId = function() {return nullValue;};
29325
+ } else if (method == 'non-adjacent') {
29227
29326
  classifyByRecordId = getNonAdjacentClassifier(lyr, dataset, values);
29228
- } else if (opts.index_field) {
29327
+ } else if (method == 'indexed') {
29229
29328
  // data is pre-classified... just read the index from a field
29230
29329
  classifyByValue = getIndexedClassifier(values, nullValue, opts);
29231
29330
  } else if (method == 'categorical') {
@@ -31140,7 +31239,11 @@ ${svg}
31140
31239
  if (!opts.force && !opts.prefix) {
31141
31240
  // overwrite existing fields if the "force" option is set.
31142
31241
  // prefix also overwrites... TODO: consider changing this
31143
- joinFields = utils.difference(joinFields, destFields);
31242
+ var duplicateFields = utils.intersection(joinFields, destFields);
31243
+ if (duplicateFields.length > 0) {
31244
+ message('Same-named fields not joined without the "force" flag:', duplicateFields);
31245
+ joinFields = utils.difference(joinFields, duplicateFields);
31246
+ }
31144
31247
  }
31145
31248
  return joinFields;
31146
31249
  }
@@ -31872,7 +31975,7 @@ ${svg}
31872
31975
  // stop("Missing required colors parameter");
31873
31976
  // }
31874
31977
  if (Array.isArray(opts.colors)) {
31875
- opts.colors.forEach(parseColor); // validate colors
31978
+ opts.colors.forEach(validateColor);
31876
31979
  }
31877
31980
 
31878
31981
  var records = lyr.data ? lyr.data.getRecords() : [];
@@ -32111,7 +32214,7 @@ ${svg}
32111
32214
  var name = cmdOpts.name;
32112
32215
  var cmdDefn = externalCommands[name];
32113
32216
  if (!cmdDefn) {
32114
- stop('Unsupported command');
32217
+ stop('Unsupported command:', name);
32115
32218
  }
32116
32219
  var targetType = cmdDefn.target;
32117
32220
  var opts = parseExternalCommand(name, cmdDefn, cmdOpts._);
@@ -34243,6 +34346,7 @@ ${svg}
34243
34346
  // old simplification data will not be optimal after reprojection;
34244
34347
  // re-using for now to avoid error in web ui
34245
34348
  zz = data.zz,
34349
+ z = arcs.getRetainedInterval(),
34246
34350
  p;
34247
34351
 
34248
34352
  for (var i=0, n=xx.length; i<n; i++) {
@@ -34251,6 +34355,7 @@ ${svg}
34251
34355
  yy[i] = p[1];
34252
34356
  }
34253
34357
  arcs.updateVertexData(data.nn, xx, yy, zz);
34358
+ arcs.setRetainedInterval(z);
34254
34359
  }
34255
34360
 
34256
34361
  function projectArcs2(arcs, proj) {
@@ -36891,8 +36996,12 @@ ${svg}
36891
36996
  // support multiline string of commands pasted into console
36892
36997
  str = str.split(/\n+/g).map(function(str) {
36893
36998
  var match = /^[a-z][\w-]*/.exec(str = str.trim());
36894
- if (match && parser.isCommandName(match[0])) {
36895
- str = '-' + str; // add hyphen prefix to bare command
36999
+ //if (match && parser.isCommandName(match[0])) {
37000
+ if (match) {
37001
+ // add hyphen prefix to bare command
37002
+ // also add hyphen to non-command strings, for a better error message
37003
+ // ("unsupported command" instead of "The -i command cannot be run in the browser")
37004
+ str = '-' + str;
36896
37005
  }
36897
37006
  return str;
36898
37007
  }).join(' ');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.5.96",
3
+ "version": "0.5.99",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -35,6 +35,7 @@
35
35
  "files": [
36
36
  "/bin/**",
37
37
  "/www/**",
38
+ "!/www/basemap.js",
38
39
  "!/www/nacis/",
39
40
  "/mapshaper.js",
40
41
  "!.DS_Store"
Binary file
Binary file
package/www/index.html CHANGED
@@ -73,7 +73,7 @@
73
73
  <input type="text" value="label" class="clicktext" />
74
74
  </div></div>
75
75
  <div id="mode-buttons" class="page-header-buttons">
76
- <span class="simplify-btn header-btn btn">Simplify</span><span class="separator"></span><span class="console-btn header-btn btn">Console</span><span class="separator"></span><span class="export-btn header-btn btn">Export</span>
76
+ <span class="basemap-btn header-btn btn">Basemap</span><span class="separator"></span><span class="simplify-btn header-btn btn">Simplify</span><span class="separator"></span><span class="console-btn header-btn btn">Console</span><span class="separator"></span><span class="export-btn header-btn btn">Export</span>
77
77
  </div>
78
78
  <div id="splash-buttons" class="page-header-buttons">
79
79
  <a href="https://github.com/mbloch/mapshaper/wiki"><span id="wiki-btn" class="header-btn btn">Wiki</span></a><span class="separator"></span><a href="https://github.com/mbloch/mapshaper"><span id="github-btn" class="header-btn btn">GitHub</span></a>
@@ -148,6 +148,18 @@
148
148
  </div>
149
149
  </div>
150
150
 
151
+ <div class="basemap-options main-area popup-dialog">
152
+ <div class="info-box">
153
+ <h3>Basemap options</h3>
154
+ <p>Basemaps are only displayed if the active layer has WGS84 or Web Mercator coordinates.</p>
155
+ <p class="basemap-error"></p>
156
+ <div class="basemap-styles"></div>
157
+ <div>
158
+ <div class="close-btn btn dialog-btn">Close</div>
159
+ </div>
160
+ </div>
161
+ </div>
162
+
151
163
  <div class="simplify-options main-area popup-dialog">
152
164
  <div class="info-box">
153
165
  <h3>Simplification menu</h3>
@@ -280,6 +292,7 @@ interface. Examples: "no-topology"
280
292
  <div class="repair-btn text-btn colored-text">Repair</div>
281
293
  </div>
282
294
  <div class="map-layers"></div>
295
+ <div class="basemap-container"><div class="basemap"></div></div>
283
296
  </div>
284
297
  </div>
285
298
 
@@ -287,6 +300,7 @@ interface. Examples: "no-topology"
287
300
  <div class="drop-area"></div>
288
301
  </div>
289
302
 
303
+ <script src="basemap.js" type="text/javascript"></script>
290
304
  <script src="zip.js" type="text/javascript"></script>
291
305
  <script src="modules.js" type="text/javascript"></script>
292
306
  <script src="mapshaper.js" type="text/javascript"></script>