svgmap 2.20.1 → 2.21.0
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/README.md +22 -0
- package/dist/index.cjs +186 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +186 -4
- package/dist/index.js.map +1 -1
- package/dist/svg-map.css +9 -0
- package/dist/svg-map.min.css +1 -1
- package/dist/svg-map.umd.js +186 -4
- package/dist/svg-map.umd.js.map +1 -1
- package/dist/svg-map.umd.min.js +1 -1
- package/dist/svgMap.css +9 -0
- package/dist/svgMap.js +186 -4
- package/dist/svgMap.js.map +1 -1
- package/dist/svgMap.min.css +1 -1
- package/dist/svgMap.min.js +1 -1
- package/package.json +1 -1
- package/src/js/core/svg-map.js +186 -4
- package/src/scss/map.scss +11 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svgmap",
|
|
3
3
|
"description": "svgMap is a JavaScript library that lets you easily create an interactable world map comparing customizable data for each country.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.21.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"keywords": [
|
package/src/js/core/svg-map.js
CHANGED
|
@@ -101,7 +101,34 @@ export default class svgMap {
|
|
|
101
101
|
showContinentSelector: false,
|
|
102
102
|
|
|
103
103
|
// Reset zoom on resize
|
|
104
|
-
resetZoomOnResize: false
|
|
104
|
+
resetZoomOnResize: false,
|
|
105
|
+
|
|
106
|
+
// Static pins: false | string[] | function(countryID, countryValues) => boolean
|
|
107
|
+
staticPins: false,
|
|
108
|
+
|
|
109
|
+
// Default pin fill color
|
|
110
|
+
pinColor: '#000000',
|
|
111
|
+
|
|
112
|
+
// Default pin stroke color and width (circle pins; width is in screen pixels with non-scaling stroke)
|
|
113
|
+
pinStrokeColor: '#ffffff',
|
|
114
|
+
pinStrokeWidth: 1.5,
|
|
115
|
+
|
|
116
|
+
// Default pin radius in SVG units (viewBox is 2000 × 1001)
|
|
117
|
+
pinSize: 8,
|
|
118
|
+
|
|
119
|
+
// Custom pin element: function(countryID, countryValues) => SVGElement | null
|
|
120
|
+
onGetPin: null,
|
|
121
|
+
|
|
122
|
+
// Image URL to use as a pin instead of the default circle (can also be set per-country via values[id].pinImage)
|
|
123
|
+
pinImage: null,
|
|
124
|
+
|
|
125
|
+
// Width and height of the pin image in SVG units (viewBox is 2000 × 1001)
|
|
126
|
+
pinImageWidth: 20,
|
|
127
|
+
pinImageHeight: 20,
|
|
128
|
+
|
|
129
|
+
// Offset from computed pin position, in SVG units (added after auto center or pinX/pinY)
|
|
130
|
+
pinOffsetX: 0,
|
|
131
|
+
pinOffsetY: 0
|
|
105
132
|
};
|
|
106
133
|
|
|
107
134
|
this.options = Object.assign({}, defaultOptions, options);
|
|
@@ -975,7 +1002,7 @@ export default class svgMap {
|
|
|
975
1002
|
}
|
|
976
1003
|
countryElement.parentNode.insertBefore(
|
|
977
1004
|
countryElement,
|
|
978
|
-
this.persistentTooltipGroup || null
|
|
1005
|
+
this.persistentTooltipGroup || this.pinGroup || null
|
|
979
1006
|
);
|
|
980
1007
|
if (setActive) {
|
|
981
1008
|
countryElement.classList.add('svgMap-active');
|
|
@@ -1095,6 +1122,10 @@ export default class svgMap {
|
|
|
1095
1122
|
this.createPersistentTooltips(countryElements);
|
|
1096
1123
|
}
|
|
1097
1124
|
|
|
1125
|
+
if (this.options.staticPins) {
|
|
1126
|
+
this.createStaticPins(countryElements);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1098
1129
|
let pointerStart = null;
|
|
1099
1130
|
let activeCountry = null;
|
|
1100
1131
|
|
|
@@ -1157,7 +1188,7 @@ export default class svgMap {
|
|
|
1157
1188
|
clearActive();
|
|
1158
1189
|
countryElement.parentNode.insertBefore(
|
|
1159
1190
|
countryElement,
|
|
1160
|
-
this.persistentTooltipGroup || null
|
|
1191
|
+
this.persistentTooltipGroup || this.pinGroup || null
|
|
1161
1192
|
);
|
|
1162
1193
|
countryElement.classList.add('svgMap-active');
|
|
1163
1194
|
this.setTooltipContent(this.getTooltipContent(countryID));
|
|
@@ -1171,7 +1202,7 @@ export default class svgMap {
|
|
|
1171
1202
|
clearActive();
|
|
1172
1203
|
countryElement.parentNode.insertBefore(
|
|
1173
1204
|
countryElement,
|
|
1174
|
-
this.persistentTooltipGroup || null
|
|
1205
|
+
this.persistentTooltipGroup || this.pinGroup || null
|
|
1175
1206
|
);
|
|
1176
1207
|
countryElement.classList.add('svgMap-active');
|
|
1177
1208
|
this.setTooltipContent(this.getTooltipContent(countryID));
|
|
@@ -1359,6 +1390,157 @@ export default class svgMap {
|
|
|
1359
1390
|
);
|
|
1360
1391
|
}
|
|
1361
1392
|
|
|
1393
|
+
// Create static pins on the map
|
|
1394
|
+
|
|
1395
|
+
createStaticPins(countryElements) {
|
|
1396
|
+
if (this.pinGroup) {
|
|
1397
|
+
this.pinGroup.remove();
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
this.pinGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
|
1401
|
+
this.pinGroup.classList.add('svgMap-pin-group');
|
|
1402
|
+
this.mapImage.appendChild(this.pinGroup);
|
|
1403
|
+
|
|
1404
|
+
countryElements.forEach(
|
|
1405
|
+
function (countryElement) {
|
|
1406
|
+
var countryID = countryElement.getAttribute('data-id');
|
|
1407
|
+
if (!this.shouldShowPin(countryID)) {
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
var countryValues = this.options.data.values[countryID];
|
|
1412
|
+
var cx, cy;
|
|
1413
|
+
|
|
1414
|
+
if (
|
|
1415
|
+
countryValues &&
|
|
1416
|
+
countryValues.pinX != null &&
|
|
1417
|
+
countryValues.pinY != null
|
|
1418
|
+
) {
|
|
1419
|
+
cx = countryValues.pinX;
|
|
1420
|
+
cy = countryValues.pinY;
|
|
1421
|
+
} else {
|
|
1422
|
+
// Split the path at absolute M commands and use the largest sub-path
|
|
1423
|
+
// to avoid overseas territories (islands, colonies) skewing the center.
|
|
1424
|
+
var d = countryElement.getAttribute('d');
|
|
1425
|
+
var subPaths = d.split(/(?=M)/).filter((s) => s.trim().length > 0);
|
|
1426
|
+
var largestBB = null;
|
|
1427
|
+
var largestArea = -1;
|
|
1428
|
+
|
|
1429
|
+
subPaths.forEach(
|
|
1430
|
+
function (subPath) {
|
|
1431
|
+
var tmp = document.createElementNS(
|
|
1432
|
+
'http://www.w3.org/2000/svg',
|
|
1433
|
+
'path'
|
|
1434
|
+
);
|
|
1435
|
+
tmp.setAttribute('d', subPath);
|
|
1436
|
+
this.mapImage.appendChild(tmp);
|
|
1437
|
+
var bb = tmp.getBBox();
|
|
1438
|
+
var area = bb.width * bb.height;
|
|
1439
|
+
if (area > largestArea) {
|
|
1440
|
+
largestArea = area;
|
|
1441
|
+
largestBB = bb;
|
|
1442
|
+
}
|
|
1443
|
+
this.mapImage.removeChild(tmp);
|
|
1444
|
+
}.bind(this)
|
|
1445
|
+
);
|
|
1446
|
+
|
|
1447
|
+
cx = largestBB.x + largestBB.width / 2;
|
|
1448
|
+
cy = largestBB.y + largestBB.height / 2;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
var offsetX =
|
|
1452
|
+
countryValues && countryValues.pinOffsetX != null
|
|
1453
|
+
? countryValues.pinOffsetX
|
|
1454
|
+
: this.options.pinOffsetX;
|
|
1455
|
+
var offsetY =
|
|
1456
|
+
countryValues && countryValues.pinOffsetY != null
|
|
1457
|
+
? countryValues.pinOffsetY
|
|
1458
|
+
: this.options.pinOffsetY;
|
|
1459
|
+
cx += offsetX;
|
|
1460
|
+
cy += offsetY;
|
|
1461
|
+
|
|
1462
|
+
var color =
|
|
1463
|
+
(countryValues && countryValues.pinColor) || this.options.pinColor;
|
|
1464
|
+
var size =
|
|
1465
|
+
(countryValues && countryValues.pinSize) || this.options.pinSize;
|
|
1466
|
+
var strokeColor =
|
|
1467
|
+
(countryValues && countryValues.pinStrokeColor) ||
|
|
1468
|
+
this.options.pinStrokeColor;
|
|
1469
|
+
var strokeWidth =
|
|
1470
|
+
(countryValues && countryValues.pinStrokeWidth) ||
|
|
1471
|
+
this.options.pinStrokeWidth;
|
|
1472
|
+
|
|
1473
|
+
if (typeof this.options.onGetPin === 'function') {
|
|
1474
|
+
var custom = this.options.onGetPin(countryID, countryValues);
|
|
1475
|
+
if (custom) {
|
|
1476
|
+
custom.setAttribute(
|
|
1477
|
+
'transform',
|
|
1478
|
+
'translate(' + cx + ',' + cy + ')'
|
|
1479
|
+
);
|
|
1480
|
+
this.pinGroup.appendChild(custom);
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
var pinImage =
|
|
1486
|
+
(countryValues && countryValues.pinImage) || this.options.pinImage;
|
|
1487
|
+
|
|
1488
|
+
if (pinImage) {
|
|
1489
|
+
var pinW =
|
|
1490
|
+
(countryValues && countryValues.pinImageWidth) ||
|
|
1491
|
+
this.options.pinImageWidth;
|
|
1492
|
+
var pinH =
|
|
1493
|
+
(countryValues && countryValues.pinImageHeight) ||
|
|
1494
|
+
this.options.pinImageHeight;
|
|
1495
|
+
var img = document.createElementNS(
|
|
1496
|
+
'http://www.w3.org/2000/svg',
|
|
1497
|
+
'image'
|
|
1498
|
+
);
|
|
1499
|
+
img.setAttribute('href', pinImage);
|
|
1500
|
+
img.setAttribute('x', cx - pinW / 2);
|
|
1501
|
+
img.setAttribute('y', cy - pinH / 2);
|
|
1502
|
+
img.setAttribute('width', pinW);
|
|
1503
|
+
img.setAttribute('height', pinH);
|
|
1504
|
+
img.setAttribute('data-id', countryID);
|
|
1505
|
+
img.classList.add('svgMap-pin');
|
|
1506
|
+
this.pinGroup.appendChild(img);
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
var circle = document.createElementNS(
|
|
1511
|
+
'http://www.w3.org/2000/svg',
|
|
1512
|
+
'circle'
|
|
1513
|
+
);
|
|
1514
|
+
circle.setAttribute('cx', cx);
|
|
1515
|
+
circle.setAttribute('cy', cy);
|
|
1516
|
+
circle.setAttribute('r', size);
|
|
1517
|
+
circle.setAttribute('fill', color);
|
|
1518
|
+
if (strokeWidth > 0) {
|
|
1519
|
+
circle.setAttribute('stroke', strokeColor);
|
|
1520
|
+
circle.setAttribute('stroke-width', strokeWidth);
|
|
1521
|
+
circle.setAttribute('vector-effect', 'non-scaling-stroke');
|
|
1522
|
+
}
|
|
1523
|
+
circle.setAttribute('data-id', countryID);
|
|
1524
|
+
circle.classList.add('svgMap-pin');
|
|
1525
|
+
this.pinGroup.appendChild(circle);
|
|
1526
|
+
}.bind(this)
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
// Check if a static pin should be shown for a country
|
|
1531
|
+
|
|
1532
|
+
shouldShowPin(countryID) {
|
|
1533
|
+
var pins = this.options.staticPins;
|
|
1534
|
+
var countryValues = this.options.data.values[countryID];
|
|
1535
|
+
if (Array.isArray(pins)) {
|
|
1536
|
+
return pins.indexOf(countryID) !== -1;
|
|
1537
|
+
}
|
|
1538
|
+
if (typeof pins === 'function') {
|
|
1539
|
+
return pins(countryID, countryValues);
|
|
1540
|
+
}
|
|
1541
|
+
return false;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1362
1544
|
// Check if a persistent tooltip should be shown on load
|
|
1363
1545
|
|
|
1364
1546
|
shouldShowTooltipOnLoad(countryID) {
|
package/src/scss/map.scss
CHANGED
|
@@ -259,3 +259,14 @@
|
|
|
259
259
|
.svgMap-wrapper.svgMap-country-click-callback .svgMap-map-wrapper .svgMap-country {
|
|
260
260
|
cursor: pointer;
|
|
261
261
|
}
|
|
262
|
+
|
|
263
|
+
// Static pins
|
|
264
|
+
|
|
265
|
+
.svgMap-pin-group {
|
|
266
|
+
pointer-events: none;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.svgMap-pin {
|
|
270
|
+
vector-effect: non-scaling-stroke;
|
|
271
|
+
transition: r 250ms;
|
|
272
|
+
}
|