dotted-map 2.1.0 → 2.2.2

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/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "dotted-map",
3
- "version": "2.1.0",
3
+ "version": "2.2.2",
4
4
  "description": "Create a SVG map filled with dots for the world or countries",
5
- "main": "./dist/index.bundle.js",
5
+ "main": "./index.js",
6
6
  "exports": {
7
- ".": "./dist/index.bundle.js",
8
- "./without-countries": "./dist/without-countries.bundle.js"
7
+ ".": "./index.js",
8
+ "./without-countries": "./without-countries.js"
9
9
  },
10
- "module": "./src/index.js",
10
+ "module": "./src/with-countries.js",
11
11
  "scripts": {
12
12
  "build": "webpack"
13
13
  },
@@ -1,7 +1,7 @@
1
1
  import proj4 from 'proj4';
2
2
  import inside from '@turf/boolean-point-in-polygon';
3
3
  import geojsonWorld from './countries.geo.json';
4
- import DottedMapWithoutCountries from './index-without-countries';
4
+ import DottedMapWithoutCountries from './without-countries';
5
5
 
6
6
  const geojsonByCountry = geojsonWorld.features.reduce((countries, feature) => {
7
7
  countries[feature.id] = feature;
@@ -11,7 +11,11 @@ const geojsonByCountry = geojsonWorld.features.reduce((countries, feature) => {
11
11
  const geojsonToMultiPolygons = (geojson) => {
12
12
  const coordinates = geojson.features.reduce(
13
13
  (poly, feature) =>
14
- poly.concat(feature.geometry.type === 'Polygon' ? [feature.geometry.coordinates] : feature.geometry.coordinates),
14
+ poly.concat(
15
+ feature.geometry.type === 'Polygon'
16
+ ? [feature.geometry.coordinates]
17
+ : feature.geometry.coordinates,
18
+ ),
15
19
  [],
16
20
  );
17
21
  return { type: 'Feature', geometry: { type: 'MultiPolygon', coordinates } };
@@ -41,7 +45,10 @@ const computeGeojsonBox = (geojson) => {
41
45
  } else if (type == 'Feature') {
42
46
  return computeGeojsonBox(geometry);
43
47
  } else if (type === 'MultiPolygon') {
44
- return computeGeojsonBox({ type: 'Polygon', coordinates: coordinates.flat() });
48
+ return computeGeojsonBox({
49
+ type: 'Polygon',
50
+ coordinates: coordinates.flat(),
51
+ });
45
52
  } else if (type == 'Polygon') {
46
53
  const coords = coordinates.flat();
47
54
  const latitudes = coords.map(([_lng, lat]) => lat);
@@ -62,7 +69,13 @@ const computeGeojsonBox = (geojson) => {
62
69
  }
63
70
  };
64
71
 
65
- const getMap = ({ height = 0, width = 0, countries = [], region, grid = 'vertical' }) => {
72
+ const getMap = ({
73
+ height = 0,
74
+ width = 0,
75
+ countries = [],
76
+ region,
77
+ grid = 'vertical',
78
+ }) => {
66
79
  if (height <= 0 && width <= 0) {
67
80
  throw new Error('height or width is required');
68
81
  }
@@ -82,8 +95,14 @@ const getMap = ({ height = 0, width = 0, countries = [], region, grid = 'vertica
82
95
 
83
96
  const poly = geojsonToMultiPolygons(geojson);
84
97
 
85
- const [X_MIN, Y_MIN] = proj4(proj4.defs('GOOGLE'), [region.lng.min, region.lat.min]);
86
- const [X_MAX, Y_MAX] = proj4(proj4.defs('GOOGLE'), [region.lng.max, region.lat.max]);
98
+ const [X_MIN, Y_MIN] = proj4(proj4.defs('GOOGLE'), [
99
+ region.lng.min,
100
+ region.lat.min,
101
+ ]);
102
+ const [X_MAX, Y_MAX] = proj4(proj4.defs('GOOGLE'), [
103
+ region.lng.max,
104
+ region.lat.max,
105
+ ]);
87
106
  const X_RANGE = X_MAX - X_MIN;
88
107
  const Y_RANGE = Y_MAX - Y_MIN;
89
108
 
@@ -101,8 +120,15 @@ const getMap = ({ height = 0, width = 0, countries = [], region, grid = 'vertica
101
120
  const localx = y % 2 === 0 && grid === 'diagonal' ? x + 0.5 : x;
102
121
  const localy = y * ystep;
103
122
 
104
- const pointGoogle = [(localx / width) * X_RANGE + X_MIN, Y_MAX - (localy / height) * Y_RANGE];
105
- const wgs84Point = proj4(proj4.defs('GOOGLE'), proj4.defs('WGS84'), pointGoogle);
123
+ const pointGoogle = [
124
+ (localx / width) * X_RANGE + X_MIN,
125
+ Y_MAX - (localy / height) * Y_RANGE,
126
+ ];
127
+ const wgs84Point = proj4(
128
+ proj4.defs('GOOGLE'),
129
+ proj4.defs('WGS84'),
130
+ pointGoogle,
131
+ );
106
132
 
107
133
  if (inside(wgs84Point, poly)) {
108
134
  points[[x, y].join(';')] = { x: localx, y: localy };
@@ -122,16 +148,31 @@ const getMap = ({ height = 0, width = 0, countries = [], region, grid = 'vertica
122
148
  grid,
123
149
  height,
124
150
  width,
151
+ ystep,
125
152
  };
126
153
  };
127
154
 
128
155
  export const getMapJSON = (props) => JSON.stringify(getMap(props));
129
156
 
130
- function DottedMap({ avoidOuterPins = false, ...args }) {
131
- const map = getMap(args);
157
+ const getCacheKey = ({
158
+ height = 0,
159
+ width = 0,
160
+ countries = [],
161
+ region,
162
+ grid = 'vertical',
163
+ }) => {
164
+ return [
165
+ JSON.stringify(region),
166
+ grid,
167
+ height,
168
+ width,
169
+ JSON.stringify(countries),
170
+ ].join(' ');
171
+ };
132
172
 
133
- // const cacheKey = [JSON.stringify(region), grid, height, width, JSON.stringify(countries)].join(' ');
134
- // const map = CACHE[cacheKey];
173
+ function DottedMap({ avoidOuterPins = false, ...args }) {
174
+ const cacheKey = getCacheKey(args);
175
+ const map = CACHE[cacheKey] || getMap(args);
135
176
 
136
177
  return new DottedMapWithoutCountries({ avoidOuterPins, map });
137
178
  }
@@ -2,16 +2,41 @@ import proj4 from 'proj4';
2
2
  import inside from '@turf/boolean-point-in-polygon';
3
3
 
4
4
  function DottedMapWithoutCountries({ map, avoidOuterPins = false }) {
5
- const { points, X_MIN, Y_MAX, X_RANGE, Y_RANGE, region, grid, width, height } = map;
5
+ const {
6
+ points,
7
+ X_MIN,
8
+ Y_MAX,
9
+ X_RANGE,
10
+ Y_RANGE,
11
+ region,
12
+ grid,
13
+ width,
14
+ height,
15
+ ystep,
16
+ } = map;
6
17
 
7
18
  return {
8
19
  addPin({ lat, lng, data, svgOptions }) {
20
+ const pin = this.getPin({ lat, lng });
21
+ const point = { ...pin, data, svgOptions };
22
+
23
+ points[[point.x, point.y].join(';')] = point;
24
+
25
+ return point;
26
+ },
27
+ getPin({ lat, lng }) {
9
28
  const [googleX, googleY] = proj4(proj4.defs('GOOGLE'), [lng, lat]);
10
29
  if (avoidOuterPins) {
11
- const wgs84Point = proj4(proj4.defs('GOOGLE'), proj4.defs('WGS84'), [googleX, googleY]);
30
+ const wgs84Point = proj4(proj4.defs('GOOGLE'), proj4.defs('WGS84'), [
31
+ googleX,
32
+ googleY,
33
+ ]);
12
34
  if (!inside(wgs84Point, poly)) return;
13
35
  }
14
- let [rawX, rawY] = [(width * (googleX - X_MIN)) / X_RANGE, (height * (Y_MAX - googleY)) / Y_RANGE];
36
+ let [rawX, rawY] = [
37
+ (width * (googleX - X_MIN)) / X_RANGE,
38
+ (height * (Y_MAX - googleY)) / Y_RANGE,
39
+ ];
15
40
  const y = Math.round(rawY / ystep);
16
41
  if (y % 2 === 0 && grid === 'diagonal') {
17
42
  rawX -= 0.5;
@@ -22,20 +47,34 @@ function DottedMapWithoutCountries({ map, avoidOuterPins = false }) {
22
47
  localx += 0.5;
23
48
  }
24
49
 
25
- const point = { x: localx, y: localy, data, svgOptions };
50
+ const [localLng, localLat] = proj4(
51
+ proj4.defs('GOOGLE'),
52
+ proj4.defs('WGS84'),
53
+ [
54
+ (localx * X_RANGE) / width + X_MIN,
55
+ Y_MAX - (localy * Y_RANGE) / height,
56
+ ],
57
+ );
26
58
 
27
- points[[x, y].join(';')] = point;
59
+ const pin = { x: localx, y: localy, lat: localLat, lng: localLng };
28
60
 
29
- return point;
61
+ return pin;
30
62
  },
31
63
  getPoints() {
32
64
  return Object.values(points);
33
65
  },
34
- getSVG({ shape = 'circle', color = 'current', backgroundColor = 'transparent', radius = 0.5 }) {
66
+ getSVG({
67
+ shape = 'circle',
68
+ color = 'current',
69
+ backgroundColor = 'transparent',
70
+ radius = 0.5,
71
+ }) {
35
72
  const getPoint = ({ x, y, svgOptions = {} }) => {
36
73
  const pointRadius = svgOptions.radius || radius;
37
74
  if (shape === 'circle') {
38
- return `<circle cx="${x}" cy="${y}" r="${pointRadius}" fill="${svgOptions.color || color}" />`;
75
+ return `<circle cx="${x}" cy="${y}" r="${pointRadius}" fill="${
76
+ svgOptions.color || color
77
+ }" />`;
39
78
  } else if (shape === 'hexagon') {
40
79
  const sqrt3radius = Math.sqrt(3) * pointRadius;
41
80
 
@@ -48,9 +87,9 @@ function DottedMapWithoutCountries({ map, avoidOuterPins = false }) {
48
87
  [x, y - 2 * pointRadius],
49
88
  ];
50
89
 
51
- return `<polyline points="${polyPoints.map((point) => point.join(',')).join(' ')}" fill="${
52
- svgOptions.color || color
53
- }" />`;
90
+ return `<polyline points="${polyPoints
91
+ .map((point) => point.join(','))
92
+ .join(' ')}" fill="${svgOptions.color || color}" />`;
54
93
  }
55
94
  };
56
95
 
package/webpack.config.js CHANGED
@@ -1,23 +1,37 @@
1
1
  const path = require('path');
2
+ const fs = require('fs');
3
+
4
+ class CleanOutput {
5
+ apply(compiler) {
6
+ compiler.hooks.thisCompilation.tap('CleanOutput', () => {
7
+ if (fs.existsSync('./index.js')) {
8
+ fs.rmSync('./index.js');
9
+ }
10
+ if (fs.existsSync('./without-countries.js')) {
11
+ fs.rmSync('./without-countries.js');
12
+ }
13
+ });
14
+ }
15
+ }
2
16
 
3
17
  module.exports = {
4
18
  entry: {
5
- index: './src/index.js',
6
- ['without-countries']: './src/index-without-countries.js',
19
+ index: './src/with-countries.js',
20
+ 'without-countries': './src/without-countries.js',
7
21
  },
8
22
  mode: 'production',
9
23
  output: {
10
- path: path.resolve(__dirname, 'dist'),
11
- filename: '[name].bundle.js',
24
+ path: path.resolve(__dirname),
25
+ filename: '[name].js',
12
26
  library: {
13
27
  name: 'dotted-map',
14
28
  type: 'umd',
15
29
  },
16
30
  globalObject: 'this',
17
- clean: true,
18
31
  },
19
32
  externals: {
20
33
  '@turf/boolean-point-in-polygon': '@turf/boolean-point-in-polygon',
21
34
  proj4: 'proj4',
22
35
  },
36
+ plugins: [new CleanOutput()],
23
37
  };
@@ -0,0 +1,70 @@
1
+ namespace DottedMapWithoutCountriesLib {
2
+ interface Region {
3
+ lat: { min: number; max: number };
4
+ lng: { min: number; max: number };
5
+ }
6
+
7
+ interface Map {
8
+ points: Point[];
9
+ X_MIN: number;
10
+ Y_MAX: number;
11
+ X_RANGE: number;
12
+ Y_RANGE: number;
13
+ region: Region;
14
+ grid: 'vertical' | 'diagonal';
15
+ width: number;
16
+ height: number;
17
+ ystep: number;
18
+ }
19
+
20
+ interface Settings extends MapSettings {
21
+ map: Map;
22
+ avoidOuterPins?: false | true;
23
+ }
24
+
25
+ interface SvgOptions {
26
+ color?: string;
27
+ radius?: number;
28
+ }
29
+
30
+ interface Pin {
31
+ lat: number;
32
+ lng: number;
33
+ data?: any;
34
+ svgOptions?: SvgOptions;
35
+ }
36
+
37
+ interface SvgSettings {
38
+ shape?: 'circle' | 'hexagon';
39
+ color?: string;
40
+ backgroundColor?: string;
41
+ radius?: number;
42
+ }
43
+
44
+ type Point = {
45
+ x: number;
46
+ y: number;
47
+ lat: number;
48
+ lng: number;
49
+ data?: any;
50
+ svgOptions?: SvgOptions;
51
+ };
52
+ }
53
+
54
+ export default class DottedMapWithoutCountries {
55
+ constructor(settings: DottedMapWithoutCountriesLib.Settings);
56
+
57
+ addPin(
58
+ pin: DottedMapWithoutCountriesLib.Pin,
59
+ ): DottedMapWithoutCountriesLib.Point;
60
+ getPin(
61
+ pin: DottedMapWithoutCountriesLib.Pin,
62
+ ): DottedMapWithoutCountriesLib.Point;
63
+ getPoints(): DottedMapWithoutCountriesLib.Point[];
64
+ getSVG(settings: DottedMapWithoutCountriesLib.SvgSettings): string;
65
+ image: {
66
+ region: DottedMap.Region;
67
+ width: number;
68
+ height: number;
69
+ };
70
+ }
@@ -0,0 +1 @@
1
+ !function(o,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("proj4"),require("@turf/boolean-point-in-polygon")):"function"==typeof define&&define.amd?define(["proj4","@turf/boolean-point-in-polygon"],e):"object"==typeof exports?exports["dotted-map"]=e(require("proj4"),require("@turf/boolean-point-in-polygon")):o["dotted-map"]=e(o.proj4,o["@turf/boolean-point-in-polygon"])}(this,(function(o,e){return(()=>{"use strict";var t={620:o=>{o.exports=e},25:e=>{e.exports=o}},n={};function r(o){var e=n[o];if(void 0!==e)return e.exports;var i=n[o]={exports:{}};return t[o](i,i.exports,r),i.exports}r.n=o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return r.d(e,{a:e}),e},r.d=(o,e)=>{for(var t in e)r.o(e,t)&&!r.o(o,t)&&Object.defineProperty(o,t,{enumerable:!0,get:e[t]})},r.o=(o,e)=>Object.prototype.hasOwnProperty.call(o,e),r.r=o=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})};var i={};return(()=>{r.r(i),r.d(i,{default:()=>a});var o=r(25),e=r.n(o),t=r(620),n=r.n(t);const a=function({map:o,avoidOuterPins:t=!1}){const{points:r,X_MIN:i,Y_MAX:a,X_RANGE:s,Y_RANGE:l,region:p,grid:u,width:d,height:c,ystep:f}=o;return{addPin({lat:o,lng:e,data:t,svgOptions:n}){const i={...this.getPin({lat:o,lng:e}),data:t,svgOptions:n};return r[[i.x,i.y].join(";")]=i,i},getPin({lat:o,lng:r}){const[p,g]=e()(e().defs("GOOGLE"),[r,o]);if(t){const o=e()(e().defs("GOOGLE"),e().defs("WGS84"),[p,g]);if(!n()(o,poly))return}let[y,v]=[d*(p-i)/s,c*(a-g)/l];const b=Math.round(v/f);b%2==0&&"diagonal"===u&&(y-=.5);const j=Math.round(y);let[x,O]=[j,Math.round(b)*f];b%2==0&&"diagonal"===u&&(x+=.5);const[h,m]=e()(e().defs("GOOGLE"),e().defs("WGS84"),[x*s/d+i,a-O*l/c]);return{x,y:O,lat:m,lng:h}},getPoints:()=>Object.values(r),getSVG:({shape:o="circle",color:e="current",backgroundColor:t="transparent",radius:n=.5})=>`<svg viewBox="0 0 ${d} ${c}" xmlns="http://www.w3.org/2000/svg" style="background-color: ${t}">\n ${Object.values(r).map((({x:t,y:r,svgOptions:i={}})=>{const a=i.radius||n;if("circle"===o)return`<circle cx="${t}" cy="${r}" r="${a}" fill="${i.color||e}" />`;if("hexagon"===o){const o=Math.sqrt(3)*a;return`<polyline points="${[[t+o,r-a],[t+o,r+a],[t,r+2*a],[t-o,r+a],[t-o,r-a],[t,r-2*a]].map((o=>o.join(","))).join(" ")}" fill="${i.color||e}" />`}})).join("\n")}\n </svg>`,image:{region:p,width:d,height:c}}}})(),i})()}));