@superrouteca/smap 1.0.5 → 1.0.6
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 +5 -0
- package/README.md +3 -2
- package/dist/SOURCE.json +7 -7
- package/dist/smap-client.cjs +2 -2
- package/dist/smap-client.js +2 -2
- package/dist/smap-client.mjs +2 -2
- package/dist/smap.cjs +72 -13
- package/dist/smap.js +71 -12
- package/dist/smap.mjs +72 -13
- package/package.json +1 -1
- package/types/smap.d.cts +5 -1
- package/types/smap.d.mts +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.6 — 2026-10-27
|
|
4
|
+
|
|
5
|
+
- Close up (from zoom 13, `bakeZoom`) each pin's number is drawn into the pin, so where pins overlap the pin on top covers the one below completely.
|
|
6
|
+
- Marker shape `vehicle`: the route map's live position, a white circle with a truck in each feature's own colour, in one layer for any number of drivers. Point labels can sit to the right (`labelPosition: 'right'`).
|
|
7
|
+
|
|
3
8
|
## 1.0.5 — 2026-10-27
|
|
4
9
|
|
|
5
10
|
- Auto Zoom has a switch: the map option `autoZoom` and `map.setAutoZoom(on)`. In 3D, W / S tilt and A / D turn the view (`keyboard3D`).
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ areas drawn on the GPU (hundreds of thousands of points, clustered or not), 3D b
|
|
|
10
10
|
renew themselves. Also the JS client (no map view) for servers and workers: tokens, the nearest node, styles, tiles
|
|
11
11
|
and raw reads.
|
|
12
12
|
|
|
13
|
-
- Version 1.0.
|
|
13
|
+
- Version 1.0.6, MIT licence (see `LICENSE` at the repository root)
|
|
14
14
|
- Works with bundlers (Vite, webpack, Next.js and others): ES module and CommonJS entry points with types
|
|
15
15
|
- Nothing else to install: the map renderer is bundled in the package
|
|
16
16
|
- Importing is safe on a server; a map is created in the browser only
|
|
@@ -159,7 +159,7 @@ with `default` for features without it) or an engine expression (an array such a
|
|
|
159
159
|
|
|
160
160
|
| Option | Meaning |
|
|
161
161
|
|---|---|
|
|
162
|
-
| `shape` | `'pin'` (default; the tip is at the position) or `'
|
|
162
|
+
| `shape` | `'pin'` (default; the tip is at the position), `'circle'`, or `'vehicle'` (a white circle with a truck in the `border` colour, the route map's live position) |
|
|
163
163
|
| `fill` | inside colour (default white) |
|
|
164
164
|
| `border` | border colour (default the layer's `color`) |
|
|
165
165
|
| `borderWidth` | pixels (default 3) |
|
|
@@ -169,6 +169,7 @@ with `default` for features without it) or an engine expression (an array such a
|
|
|
169
169
|
| `badge` | a red count at the upper right, shown when more than 1 |
|
|
170
170
|
| `opacity` | of the pin, its number and its badge together (e.g. settled stops paler) |
|
|
171
171
|
| `overlap` | Auto Zoom for this layer (map option `autoZoom`, `map.setAutoZoom(on)`, on by default): pins piled up under a click: 4 or more within 12 px zoom the map in by 2; close up (zoom 17) or at one spot a chooser lists them, `label(properties)` names each row; `false` turns it off |
|
|
172
|
+
| `bakeZoom` | from this zoom on (default 13) each pin's number is drawn into the pin, so an upper pin covers a lower one completely; `false` keeps numbers a layer of their own |
|
|
172
173
|
| `hoverRaise` | the pin under the pointer comes to the front, so overlapping pins can be read and clicked (default `true`) |
|
|
173
174
|
| `scale` | size factor of the pin, its number and its badge together; a number or an expression of the zoom, e.g. `['interpolate', ['linear'], ['zoom'], 9, 0.5, 14, 1]` |
|
|
174
175
|
| `textMinzoom`, `badgeMinzoom` | show numbers / badges only from this zoom on, so an overview of many stops stays readable |
|
package/dist/SOURCE.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"sdkVersion": "1.0.
|
|
2
|
+
"sdkVersion": "1.0.6",
|
|
3
3
|
"engine": "maplibre-gl 6.16.0",
|
|
4
4
|
"files": {
|
|
5
|
-
"smap.js": "
|
|
5
|
+
"smap.js": "ebb6560db4ed5564693ebbf19b030bba0d5bbcc3fee2f7e2b5bf959584ffba18",
|
|
6
6
|
"smap.css": "5e3bdcb00b8fc8805f545b76cdeea5e783c89984f48ec2fee66c4319af4ada0b",
|
|
7
|
-
"smap-client.js": "
|
|
7
|
+
"smap-client.js": "87d4eaad1204383570d6d3655b52a45f19e6698b8fdbaa42c82a03471cba2e3d",
|
|
8
8
|
"smap-client.d.ts": "ad701612630a290b2dc0e49250ae25cea965ecb3a145c016bb462cd30f108cf7",
|
|
9
|
-
"smap.mjs": "
|
|
10
|
-
"smap.cjs": "
|
|
11
|
-
"smap-client.cjs": "
|
|
12
|
-
"smap-client.mjs": "
|
|
9
|
+
"smap.mjs": "6639dc281f3af69b45164c842aa83d2096e002a0c55f41ab12aa4ad9878a34e0",
|
|
10
|
+
"smap.cjs": "37865209689abe5a06ee251dc21dcf977c16ddadcb02dddab37cb0b470d7822d",
|
|
11
|
+
"smap-client.cjs": "ab2b816c894027712082f23b944349cba6d7d33f1f262d1d2c495cddf07008bd",
|
|
12
|
+
"smap-client.mjs": "91587c5d58c1341ffdcd133c74aa8d393b23e5fe0d20fe5beac25e5f5bb6647b",
|
|
13
13
|
"smap-client.d.cts": "80b96f5a907caf6295ca073816dc526e8d285f22670c809adaab5242a018e686",
|
|
14
14
|
"smap-client.d.mts": "a66834cab868a6a0eaf943c1b185a236916cb00ecf32a871f972ab3213eddeba",
|
|
15
15
|
"vendor-licenses.txt": "ee5fc05a0677eaf69601d2c7db0d9ecd6cc27c3abc1d0733bc9ed34707cf8ef2"
|
package/dist/smap-client.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Generated by js/build.mjs from js/src (see SOURCE.json). Do not edit. */
|
|
2
|
-
/*! sMap JS client 1.0.
|
|
2
|
+
/*! sMap JS client 1.0.6 — tokens, the nearest node, styles, tiles and raw reads, without a map view. */
|
|
3
3
|
/*
|
|
4
4
|
* Runs wherever `fetch` exists: browsers, Node.js 18+, workers; elsewhere (mini programs, older runtimes) pass your
|
|
5
5
|
* own `fetch`. UMD: `window.SMapClient`, `require('smap-client')`, or an AMD module.
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
}(typeof self !== 'undefined' ? self : this, function () {
|
|
20
20
|
'use strict';
|
|
21
21
|
|
|
22
|
-
var VERSION = '1.0.
|
|
22
|
+
var VERSION = '1.0.6';
|
|
23
23
|
var NODE_TTL = 3600 * 1000; // the measured order
|
|
24
24
|
var KNOWN_TTL = 30 * 86400 * 1000; // the last node list received, used when none can be read
|
|
25
25
|
|
package/dist/smap-client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sMap JS client 1.0.
|
|
1
|
+
/*! sMap JS client 1.0.6 — tokens, the nearest node, styles, tiles and raw reads, without a map view. */
|
|
2
2
|
/*
|
|
3
3
|
* Runs wherever `fetch` exists: browsers, Node.js 18+, workers; elsewhere (mini programs, older runtimes) pass your
|
|
4
4
|
* own `fetch`. UMD: `window.SMapClient`, `require('smap-client')`, or an AMD module.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
}(typeof self !== 'undefined' ? self : this, function () {
|
|
19
19
|
'use strict';
|
|
20
20
|
|
|
21
|
-
var VERSION = '1.0.
|
|
21
|
+
var VERSION = '1.0.6';
|
|
22
22
|
var NODE_TTL = 3600 * 1000; // the measured order
|
|
23
23
|
var KNOWN_TTL = 30 * 86400 * 1000; // the last node list received, used when none can be read
|
|
24
24
|
|
package/dist/smap-client.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* Generated by js/build.mjs from js/src (see SOURCE.json). Do not edit. */
|
|
2
2
|
var smapClientModule = { exports: {} };
|
|
3
3
|
(function (module, exports, define) {
|
|
4
|
-
/*! sMap JS client 1.0.
|
|
4
|
+
/*! sMap JS client 1.0.6 — tokens, the nearest node, styles, tiles and raw reads, without a map view. */
|
|
5
5
|
/*
|
|
6
6
|
* Runs wherever `fetch` exists: browsers, Node.js 18+, workers; elsewhere (mini programs, older runtimes) pass your
|
|
7
7
|
* own `fetch`. UMD: `window.SMapClient`, `require('smap-client')`, or an AMD module.
|
|
@@ -21,7 +21,7 @@ var smapClientModule = { exports: {} };
|
|
|
21
21
|
}(typeof self !== 'undefined' ? self : this, function () {
|
|
22
22
|
'use strict';
|
|
23
23
|
|
|
24
|
-
var VERSION = '1.0.
|
|
24
|
+
var VERSION = '1.0.6';
|
|
25
25
|
var NODE_TTL = 3600 * 1000; // the measured order
|
|
26
26
|
var KNOWN_TTL = 30 * 86400 * 1000; // the last node list received, used when none can be read
|
|
27
27
|
|
package/dist/smap.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Generated by js/build.mjs from js/src (see SOURCE.json). Do not edit. */
|
|
2
2
|
'use strict';
|
|
3
|
-
/*! sMap Web SDK 1.0.
|
|
3
|
+
/*! sMap Web SDK 1.0.6. Bundles maplibre-gl 6.16.0 (BSD-3-Clause), see vendor-licenses.txt. */
|
|
4
4
|
|
|
5
5
|
var smapCore = null;
|
|
6
6
|
function smapCreateEngine() {
|
|
@@ -26873,7 +26873,7 @@ function smapCreateSdk(engine) {
|
|
|
26873
26873
|
})(typeof self !== 'undefined' ? self : this, function (engine) {
|
|
26874
26874
|
'use strict';
|
|
26875
26875
|
|
|
26876
|
-
var VERSION = '1.0.
|
|
26876
|
+
var VERSION = '1.0.6';
|
|
26877
26877
|
var FLAVORS = ['light', 'white', 'grayscale', 'dark', 'black'];
|
|
26878
26878
|
var BASEMAP_SOURCE = 'basemap';
|
|
26879
26879
|
var BUILDINGS_LAYER = 'smap-buildings-3d';
|
|
@@ -27028,7 +27028,7 @@ function smapCreateSdk(engine) {
|
|
|
27028
27028
|
// from the position (right of the round part, as the page's badge sits on the turned pin's corner).
|
|
27029
27029
|
function markerGeometry(shape, size) {
|
|
27030
27030
|
var k = size / 32;
|
|
27031
|
-
if (shape === 'circle') {
|
|
27031
|
+
if (shape === 'circle' || shape === 'vehicle') {
|
|
27032
27032
|
return { k: k, tipToHead: 0, badge: [size * 0.36, -size * 0.36] };
|
|
27033
27033
|
}
|
|
27034
27034
|
var half = size * SQRT1_2; // the centre of the round part, above the tip
|
|
@@ -27054,16 +27054,18 @@ function smapCreateSdk(engine) {
|
|
|
27054
27054
|
|
|
27055
27055
|
// Each draw function gets a 2D context already scaled to the pixel ratio and returns nothing; sizes are in pixels.
|
|
27056
27056
|
var IMAGE_KINDS = {
|
|
27057
|
-
// pin|shape|fill|border|borderWidth|size
|
|
27057
|
+
// pin|shape|fill|border|borderWidth|size (shape pin, circle, or vehicle: the route map's live position, a white
|
|
27058
|
+
// circle with a truck in the border colour)
|
|
27058
27059
|
pin: function (args) {
|
|
27059
27060
|
var shape = args[0], fill = args[1], border = args[2], bw = Number(args[3]), size = Number(args[4]);
|
|
27060
27061
|
var g = markerGeometry(shape, size);
|
|
27061
|
-
var reach = shape === '
|
|
27062
|
+
var reach = shape === 'pin' ? g.tipToHead : size / 2; // farthest the shape goes from its centre
|
|
27062
27063
|
var w = Math.ceil(2 * reach + 2 * PIN_PAD), h = w;
|
|
27063
27064
|
return {
|
|
27064
27065
|
width: w, height: h,
|
|
27065
27066
|
draw: function (ctx, ratio) {
|
|
27066
27067
|
var c = w / 2;
|
|
27068
|
+
if (shape === 'vehicle') { drawVehicle(ctx, ratio, c, size, border); return; }
|
|
27067
27069
|
ctx.save();
|
|
27068
27070
|
ctx.translate(c, c);
|
|
27069
27071
|
var s = size / 2;
|
|
@@ -27094,6 +27096,31 @@ function smapCreateSdk(engine) {
|
|
|
27094
27096
|
},
|
|
27095
27097
|
};
|
|
27096
27098
|
},
|
|
27099
|
+
// pinnum|shape|fill|border|borderWidth|size|textColor|text: a pin with its number drawn in, so a pin above covers a
|
|
27100
|
+
// pin below completely (used close up, where few pins are in view; further out the number is its own layer).
|
|
27101
|
+
pinnum: function (args, measure) {
|
|
27102
|
+
var pin = IMAGE_KINDS.pin(args.slice(0, 5));
|
|
27103
|
+
var size = Number(args[4]), color = args[5], text = args.slice(6).join('|');
|
|
27104
|
+
var px = 14 * size / 32, font = 'bold ' + px + 'px monospace';
|
|
27105
|
+
return {
|
|
27106
|
+
width: pin.width, height: pin.height,
|
|
27107
|
+
draw: function (ctx, ratio) {
|
|
27108
|
+
pin.draw(ctx, ratio);
|
|
27109
|
+
if (text === '') { return; }
|
|
27110
|
+
ctx.save();
|
|
27111
|
+
ctx.font = font;
|
|
27112
|
+
ctx.textAlign = 'center';
|
|
27113
|
+
ctx.textBaseline = 'middle';
|
|
27114
|
+
ctx.shadowColor = 'rgba(0,0,0,0.5)';
|
|
27115
|
+
ctx.shadowOffsetX = ratio;
|
|
27116
|
+
ctx.shadowOffsetY = ratio;
|
|
27117
|
+
ctx.shadowBlur = 2 * ratio;
|
|
27118
|
+
ctx.fillStyle = color;
|
|
27119
|
+
ctx.fillText(text, pin.width / 2, pin.height / 2 + 0.5);
|
|
27120
|
+
ctx.restore();
|
|
27121
|
+
},
|
|
27122
|
+
};
|
|
27123
|
+
},
|
|
27097
27124
|
// num|color|size|text (bold, with the route map's text shadow)
|
|
27098
27125
|
num: function (args, measure) {
|
|
27099
27126
|
var color = args[0], size = Number(args[1]), text = args.slice(2).join('|');
|
|
@@ -27373,6 +27400,27 @@ function smapCreateSdk(engine) {
|
|
|
27373
27400
|
};
|
|
27374
27401
|
|
|
27375
27402
|
// Draws an image the SDK named (IMAGE_PREFIX + kind|args) and adds it to the map; other names are left alone.
|
|
27403
|
+
// The live-position marker of the route map: a white circle (85%) with a truck in the driver colour.
|
|
27404
|
+
function drawVehicle(ctx, ratio, c, size, color) {
|
|
27405
|
+
var r = size / 2, k = size / 24;
|
|
27406
|
+
ctx.save();
|
|
27407
|
+
ctx.translate(c, c);
|
|
27408
|
+
ctx.shadowColor = 'rgba(0,0,0,0.5)';
|
|
27409
|
+
ctx.shadowBlur = 2 * ratio;
|
|
27410
|
+
ctx.beginPath(); ctx.arc(0, 0, r, 0, Math.PI * 2);
|
|
27411
|
+
ctx.fillStyle = 'rgba(255,255,255,0.85)'; ctx.fill();
|
|
27412
|
+
ctx.shadowColor = 'transparent';
|
|
27413
|
+
ctx.scale(k, k);
|
|
27414
|
+
ctx.fillStyle = color;
|
|
27415
|
+
// cargo box, cab and two wheels, about 14 x 10 px on a 24 px marker
|
|
27416
|
+
ctx.fillRect(-7, -5, 8.5, 7);
|
|
27417
|
+
roundedPath(ctx, 2.2, -2.6, 4.8, 4.6, [[1.4, 1.4], [0.6, 0.6], [0, 0], [0, 0]]); ctx.fill();
|
|
27418
|
+
ctx.beginPath(); ctx.arc(-4.2, 3.4, 1.9, 0, Math.PI * 2); ctx.arc(4.1, 3.4, 1.9, 0, Math.PI * 2); ctx.fill();
|
|
27419
|
+
ctx.fillStyle = 'rgba(255,255,255,0.85)';
|
|
27420
|
+
ctx.beginPath(); ctx.arc(-4.2, 3.4, 0.7, 0, Math.PI * 2); ctx.arc(4.1, 3.4, 0.7, 0, Math.PI * 2); ctx.fill();
|
|
27421
|
+
ctx.restore();
|
|
27422
|
+
}
|
|
27423
|
+
|
|
27376
27424
|
SMap.prototype._drawImage = function (id) {
|
|
27377
27425
|
if (typeof id !== 'string' || id.indexOf(IMAGE_PREFIX) !== 0) { return; }
|
|
27378
27426
|
var m = this.engine;
|
|
@@ -27553,7 +27601,7 @@ function smapCreateSdk(engine) {
|
|
|
27553
27601
|
if (hit.o.marker && popupOptions.offset === undefined && this._popupDefaults.offset === undefined) {
|
|
27554
27602
|
// Just above the pin as it is drawn now (its scale may follow the zoom).
|
|
27555
27603
|
var mk = hit.o.marker, size = mk.size || 32, k = scaleAt(mk.scale, m.getZoom ? m.getZoom() : 0);
|
|
27556
|
-
popupOptions.offset = mk.shape === 'circle' ? Math.round((size / 2) * k + 4) : Math.round((markerGeometry('pin', size).tipToHead + size / 2) * k + 2);
|
|
27604
|
+
popupOptions.offset = mk.shape === 'circle' || mk.shape === 'vehicle' ? Math.round((size / 2) * k + 4) : Math.round((markerGeometry('pin', size).tipToHead + size / 2) * k + 2);
|
|
27557
27605
|
}
|
|
27558
27606
|
// Above the pin, always (as on Superroute's route map); the map pans to make room instead of flipping it below.
|
|
27559
27607
|
if (hit.o.marker && popupOptions.anchor === undefined && this._popupDefaults.anchor === undefined) { popupOptions.anchor = 'bottom'; }
|
|
@@ -27820,6 +27868,7 @@ function smapCreateSdk(engine) {
|
|
|
27820
27868
|
// The engine refuses a filter key whose value is undefined (unclustered points have none).
|
|
27821
27869
|
if (layer.filter === undefined) { delete layer.filter; }
|
|
27822
27870
|
if (layer.minzoom === undefined) { delete layer.minzoom; }
|
|
27871
|
+
if (layer.maxzoom === undefined) { delete layer.maxzoom; }
|
|
27823
27872
|
if (layer.paint === undefined) { delete layer.paint; }
|
|
27824
27873
|
// A layer's own minzoom (a marker's textMinzoom / badgeMinzoom) never shows it before the layer's own range.
|
|
27825
27874
|
for (var k in range) { layer[k] = k === 'minzoom' && layer.minzoom !== undefined ? Math.max(layer.minzoom, range.minzoom) : range[k]; }
|
|
@@ -27857,7 +27906,7 @@ function smapCreateSdk(engine) {
|
|
|
27857
27906
|
// Pins like Superroute's route map, drawn on the GPU: one image per colour pair (and per number, per badge),
|
|
27858
27907
|
// made the first time a feature shows it. Numbers and badges are their own layers above the pins.
|
|
27859
27908
|
var mk = o.marker;
|
|
27860
|
-
var shape = mk.shape === 'circle'
|
|
27909
|
+
var shape = mk.shape === 'circle' || mk.shape === 'vehicle' ? mk.shape : 'pin';
|
|
27861
27910
|
var size = mk.size || 32;
|
|
27862
27911
|
var bw = mk.borderWidth !== undefined ? mk.borderWidth : 3;
|
|
27863
27912
|
var g = markerGeometry(shape, size);
|
|
@@ -27868,22 +27917,29 @@ function smapCreateSdk(engine) {
|
|
|
27868
27917
|
// Opacity of the pin, its number and its badge together (the route map draws settled stops at .72).
|
|
27869
27918
|
var markerPaint = mk.opacity !== undefined ? { 'icon-opacity': valueExpr(mk.opacity, 1) } : undefined;
|
|
27870
27919
|
main = src + '-points';
|
|
27920
|
+
// From bakeZoom on (default 13) a pin's number is drawn into its own image, so an upper pin covers a lower
|
|
27921
|
+
// one completely. Further out, where thousands of pins can be in view, the numbers stay one layer above the
|
|
27922
|
+
// pins (an image per colour pair instead of per pin and number). bakeZoom: false keeps them separate.
|
|
27923
|
+
var plainPin = drawnImageId('pin', [shape, str(mk.fill, '#ffffff'), str(mk.border, color), String(bw), String(size)]);
|
|
27924
|
+
var bakeZoom = mk.text !== undefined && mk.bakeZoom !== false ? (mk.bakeZoom !== undefined ? mk.bakeZoom : 13) : null;
|
|
27925
|
+
var pinImage = bakeZoom === null ? plainPin : ['step', ['zoom'], plainPin, bakeZoom,
|
|
27926
|
+
drawnImageId('pinnum', [shape, str(mk.fill, '#ffffff'), str(mk.border, color), String(bw), String(size), str(mk.textColor, '#ffffff'), str(mk.text, '')])];
|
|
27871
27927
|
var markerSpecs = [];
|
|
27872
27928
|
var addMarker = function (layer) { markerSpecs.push(JSON.parse(JSON.stringify(layer))); add(layer); };
|
|
27873
27929
|
addMarker({
|
|
27874
27930
|
id: main, type: 'symbol', filter: only, paint: markerPaint,
|
|
27875
27931
|
layout: {
|
|
27876
|
-
'icon-image':
|
|
27877
|
-
'icon-anchor': shape === '
|
|
27932
|
+
'icon-image': pinImage,
|
|
27933
|
+
'icon-anchor': shape === 'pin' ? 'bottom' : 'center',
|
|
27878
27934
|
// The image has room for the shadow below the tip: the tip, not the image's edge, is at the position.
|
|
27879
|
-
'icon-offset': [0, shape === '
|
|
27935
|
+
'icon-offset': [0, shape === 'pin' ? PIN_PAD : 0], 'icon-size': scale,
|
|
27880
27936
|
'icon-allow-overlap': true, 'icon-ignore-placement': true,
|
|
27881
27937
|
},
|
|
27882
27938
|
});
|
|
27883
27939
|
if (mk.text !== undefined) {
|
|
27884
27940
|
var text = str(mk.text, '');
|
|
27885
27941
|
addMarker({
|
|
27886
|
-
id: src + '-numbers', type: 'symbol', filter: both(['!=', text, '']), minzoom: mk.textMinzoom, paint: markerPaint,
|
|
27942
|
+
id: src + '-numbers', type: 'symbol', filter: both(['!=', text, '']), minzoom: mk.textMinzoom, maxzoom: bakeZoom === null ? undefined : bakeZoom, paint: markerPaint,
|
|
27887
27943
|
layout: {
|
|
27888
27944
|
'icon-image': drawnImageId('num', [str(mk.textColor, '#ffffff'), String(size), text]),
|
|
27889
27945
|
'icon-offset': [0, -g.tipToHead], 'icon-size': scale, 'icon-allow-overlap': true, 'icon-ignore-placement': true,
|
|
@@ -27930,7 +27986,9 @@ function smapCreateSdk(engine) {
|
|
|
27930
27986
|
if (o.label) {
|
|
27931
27987
|
add({
|
|
27932
27988
|
id: src + '-labels', type: 'symbol', filter: only,
|
|
27933
|
-
layout:
|
|
27989
|
+
layout: o.labelPosition === 'right'
|
|
27990
|
+
? { 'text-field': ['to-string', ['get', o.label]], 'text-font': ['Noto Sans Regular'], 'text-size': 11, 'text-offset': [1.3, 0], 'text-anchor': 'left', 'text-optional': true, 'text-max-width': 12 }
|
|
27991
|
+
: { 'text-field': ['to-string', ['get', o.label]], 'text-font': ['Noto Sans Regular'], 'text-size': 12, 'text-offset': [0, 1.2], 'text-anchor': 'top', 'text-optional': true },
|
|
27934
27992
|
paint: { 'text-color': '#1f2937', 'text-halo-color': '#ffffff', 'text-halo-width': 1.4 },
|
|
27935
27993
|
});
|
|
27936
27994
|
}
|
|
@@ -28012,6 +28070,7 @@ function smapCreateSdk(engine) {
|
|
|
28012
28070
|
if (layer.filter === undefined) { delete layer.filter; }
|
|
28013
28071
|
if (layer.paint === undefined) { delete layer.paint; }
|
|
28014
28072
|
if (layer.minzoom === undefined) { delete layer.minzoom; }
|
|
28073
|
+
if (layer.maxzoom === undefined) { delete layer.maxzoom; }
|
|
28015
28074
|
m.addLayer(layer);
|
|
28016
28075
|
def.engineLayers.push(layer.id);
|
|
28017
28076
|
if (!top) { top = layer.id; }
|
|
@@ -28071,7 +28130,7 @@ function SMapMap(options) {
|
|
|
28071
28130
|
SMapMap.prototype = core.Map.prototype;
|
|
28072
28131
|
return new core.Map(options);
|
|
28073
28132
|
}
|
|
28074
|
-
var smapVersion = "1.0.
|
|
28133
|
+
var smapVersion = "1.0.6";
|
|
28075
28134
|
var smapStyles = ['light', 'white', 'grayscale', 'dark', 'black'];
|
|
28076
28135
|
/** The bundled rendering engine, for anything the SDK does not wrap (loaded on the first call). */
|
|
28077
28136
|
function smapGetEngine() { return smapLoad().engine; }
|
package/dist/smap.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sMap Web SDK 1.0.
|
|
1
|
+
/*! sMap Web SDK 1.0.6. Bundles maplibre-gl 6.16.0 (BSD-3-Clause), see vendor-licenses.txt. */
|
|
2
2
|
(function () {
|
|
3
3
|
function smapCreateEngine() {
|
|
4
4
|
var SMAP_BASE_URL = (typeof document !== 'undefined' && document.baseURI) || (typeof location !== 'undefined' && location.href) || 'about:blank';
|
|
@@ -26870,7 +26870,7 @@ function smapCreateSdk(engine) {
|
|
|
26870
26870
|
})(typeof self !== 'undefined' ? self : this, function (engine) {
|
|
26871
26871
|
'use strict';
|
|
26872
26872
|
|
|
26873
|
-
var VERSION = '1.0.
|
|
26873
|
+
var VERSION = '1.0.6';
|
|
26874
26874
|
var FLAVORS = ['light', 'white', 'grayscale', 'dark', 'black'];
|
|
26875
26875
|
var BASEMAP_SOURCE = 'basemap';
|
|
26876
26876
|
var BUILDINGS_LAYER = 'smap-buildings-3d';
|
|
@@ -27025,7 +27025,7 @@ function smapCreateSdk(engine) {
|
|
|
27025
27025
|
// from the position (right of the round part, as the page's badge sits on the turned pin's corner).
|
|
27026
27026
|
function markerGeometry(shape, size) {
|
|
27027
27027
|
var k = size / 32;
|
|
27028
|
-
if (shape === 'circle') {
|
|
27028
|
+
if (shape === 'circle' || shape === 'vehicle') {
|
|
27029
27029
|
return { k: k, tipToHead: 0, badge: [size * 0.36, -size * 0.36] };
|
|
27030
27030
|
}
|
|
27031
27031
|
var half = size * SQRT1_2; // the centre of the round part, above the tip
|
|
@@ -27051,16 +27051,18 @@ function smapCreateSdk(engine) {
|
|
|
27051
27051
|
|
|
27052
27052
|
// Each draw function gets a 2D context already scaled to the pixel ratio and returns nothing; sizes are in pixels.
|
|
27053
27053
|
var IMAGE_KINDS = {
|
|
27054
|
-
// pin|shape|fill|border|borderWidth|size
|
|
27054
|
+
// pin|shape|fill|border|borderWidth|size (shape pin, circle, or vehicle: the route map's live position, a white
|
|
27055
|
+
// circle with a truck in the border colour)
|
|
27055
27056
|
pin: function (args) {
|
|
27056
27057
|
var shape = args[0], fill = args[1], border = args[2], bw = Number(args[3]), size = Number(args[4]);
|
|
27057
27058
|
var g = markerGeometry(shape, size);
|
|
27058
|
-
var reach = shape === '
|
|
27059
|
+
var reach = shape === 'pin' ? g.tipToHead : size / 2; // farthest the shape goes from its centre
|
|
27059
27060
|
var w = Math.ceil(2 * reach + 2 * PIN_PAD), h = w;
|
|
27060
27061
|
return {
|
|
27061
27062
|
width: w, height: h,
|
|
27062
27063
|
draw: function (ctx, ratio) {
|
|
27063
27064
|
var c = w / 2;
|
|
27065
|
+
if (shape === 'vehicle') { drawVehicle(ctx, ratio, c, size, border); return; }
|
|
27064
27066
|
ctx.save();
|
|
27065
27067
|
ctx.translate(c, c);
|
|
27066
27068
|
var s = size / 2;
|
|
@@ -27091,6 +27093,31 @@ function smapCreateSdk(engine) {
|
|
|
27091
27093
|
},
|
|
27092
27094
|
};
|
|
27093
27095
|
},
|
|
27096
|
+
// pinnum|shape|fill|border|borderWidth|size|textColor|text: a pin with its number drawn in, so a pin above covers a
|
|
27097
|
+
// pin below completely (used close up, where few pins are in view; further out the number is its own layer).
|
|
27098
|
+
pinnum: function (args, measure) {
|
|
27099
|
+
var pin = IMAGE_KINDS.pin(args.slice(0, 5));
|
|
27100
|
+
var size = Number(args[4]), color = args[5], text = args.slice(6).join('|');
|
|
27101
|
+
var px = 14 * size / 32, font = 'bold ' + px + 'px monospace';
|
|
27102
|
+
return {
|
|
27103
|
+
width: pin.width, height: pin.height,
|
|
27104
|
+
draw: function (ctx, ratio) {
|
|
27105
|
+
pin.draw(ctx, ratio);
|
|
27106
|
+
if (text === '') { return; }
|
|
27107
|
+
ctx.save();
|
|
27108
|
+
ctx.font = font;
|
|
27109
|
+
ctx.textAlign = 'center';
|
|
27110
|
+
ctx.textBaseline = 'middle';
|
|
27111
|
+
ctx.shadowColor = 'rgba(0,0,0,0.5)';
|
|
27112
|
+
ctx.shadowOffsetX = ratio;
|
|
27113
|
+
ctx.shadowOffsetY = ratio;
|
|
27114
|
+
ctx.shadowBlur = 2 * ratio;
|
|
27115
|
+
ctx.fillStyle = color;
|
|
27116
|
+
ctx.fillText(text, pin.width / 2, pin.height / 2 + 0.5);
|
|
27117
|
+
ctx.restore();
|
|
27118
|
+
},
|
|
27119
|
+
};
|
|
27120
|
+
},
|
|
27094
27121
|
// num|color|size|text (bold, with the route map's text shadow)
|
|
27095
27122
|
num: function (args, measure) {
|
|
27096
27123
|
var color = args[0], size = Number(args[1]), text = args.slice(2).join('|');
|
|
@@ -27370,6 +27397,27 @@ function smapCreateSdk(engine) {
|
|
|
27370
27397
|
};
|
|
27371
27398
|
|
|
27372
27399
|
// Draws an image the SDK named (IMAGE_PREFIX + kind|args) and adds it to the map; other names are left alone.
|
|
27400
|
+
// The live-position marker of the route map: a white circle (85%) with a truck in the driver colour.
|
|
27401
|
+
function drawVehicle(ctx, ratio, c, size, color) {
|
|
27402
|
+
var r = size / 2, k = size / 24;
|
|
27403
|
+
ctx.save();
|
|
27404
|
+
ctx.translate(c, c);
|
|
27405
|
+
ctx.shadowColor = 'rgba(0,0,0,0.5)';
|
|
27406
|
+
ctx.shadowBlur = 2 * ratio;
|
|
27407
|
+
ctx.beginPath(); ctx.arc(0, 0, r, 0, Math.PI * 2);
|
|
27408
|
+
ctx.fillStyle = 'rgba(255,255,255,0.85)'; ctx.fill();
|
|
27409
|
+
ctx.shadowColor = 'transparent';
|
|
27410
|
+
ctx.scale(k, k);
|
|
27411
|
+
ctx.fillStyle = color;
|
|
27412
|
+
// cargo box, cab and two wheels, about 14 x 10 px on a 24 px marker
|
|
27413
|
+
ctx.fillRect(-7, -5, 8.5, 7);
|
|
27414
|
+
roundedPath(ctx, 2.2, -2.6, 4.8, 4.6, [[1.4, 1.4], [0.6, 0.6], [0, 0], [0, 0]]); ctx.fill();
|
|
27415
|
+
ctx.beginPath(); ctx.arc(-4.2, 3.4, 1.9, 0, Math.PI * 2); ctx.arc(4.1, 3.4, 1.9, 0, Math.PI * 2); ctx.fill();
|
|
27416
|
+
ctx.fillStyle = 'rgba(255,255,255,0.85)';
|
|
27417
|
+
ctx.beginPath(); ctx.arc(-4.2, 3.4, 0.7, 0, Math.PI * 2); ctx.arc(4.1, 3.4, 0.7, 0, Math.PI * 2); ctx.fill();
|
|
27418
|
+
ctx.restore();
|
|
27419
|
+
}
|
|
27420
|
+
|
|
27373
27421
|
SMap.prototype._drawImage = function (id) {
|
|
27374
27422
|
if (typeof id !== 'string' || id.indexOf(IMAGE_PREFIX) !== 0) { return; }
|
|
27375
27423
|
var m = this.engine;
|
|
@@ -27550,7 +27598,7 @@ function smapCreateSdk(engine) {
|
|
|
27550
27598
|
if (hit.o.marker && popupOptions.offset === undefined && this._popupDefaults.offset === undefined) {
|
|
27551
27599
|
// Just above the pin as it is drawn now (its scale may follow the zoom).
|
|
27552
27600
|
var mk = hit.o.marker, size = mk.size || 32, k = scaleAt(mk.scale, m.getZoom ? m.getZoom() : 0);
|
|
27553
|
-
popupOptions.offset = mk.shape === 'circle' ? Math.round((size / 2) * k + 4) : Math.round((markerGeometry('pin', size).tipToHead + size / 2) * k + 2);
|
|
27601
|
+
popupOptions.offset = mk.shape === 'circle' || mk.shape === 'vehicle' ? Math.round((size / 2) * k + 4) : Math.round((markerGeometry('pin', size).tipToHead + size / 2) * k + 2);
|
|
27554
27602
|
}
|
|
27555
27603
|
// Above the pin, always (as on Superroute's route map); the map pans to make room instead of flipping it below.
|
|
27556
27604
|
if (hit.o.marker && popupOptions.anchor === undefined && this._popupDefaults.anchor === undefined) { popupOptions.anchor = 'bottom'; }
|
|
@@ -27817,6 +27865,7 @@ function smapCreateSdk(engine) {
|
|
|
27817
27865
|
// The engine refuses a filter key whose value is undefined (unclustered points have none).
|
|
27818
27866
|
if (layer.filter === undefined) { delete layer.filter; }
|
|
27819
27867
|
if (layer.minzoom === undefined) { delete layer.minzoom; }
|
|
27868
|
+
if (layer.maxzoom === undefined) { delete layer.maxzoom; }
|
|
27820
27869
|
if (layer.paint === undefined) { delete layer.paint; }
|
|
27821
27870
|
// A layer's own minzoom (a marker's textMinzoom / badgeMinzoom) never shows it before the layer's own range.
|
|
27822
27871
|
for (var k in range) { layer[k] = k === 'minzoom' && layer.minzoom !== undefined ? Math.max(layer.minzoom, range.minzoom) : range[k]; }
|
|
@@ -27854,7 +27903,7 @@ function smapCreateSdk(engine) {
|
|
|
27854
27903
|
// Pins like Superroute's route map, drawn on the GPU: one image per colour pair (and per number, per badge),
|
|
27855
27904
|
// made the first time a feature shows it. Numbers and badges are their own layers above the pins.
|
|
27856
27905
|
var mk = o.marker;
|
|
27857
|
-
var shape = mk.shape === 'circle'
|
|
27906
|
+
var shape = mk.shape === 'circle' || mk.shape === 'vehicle' ? mk.shape : 'pin';
|
|
27858
27907
|
var size = mk.size || 32;
|
|
27859
27908
|
var bw = mk.borderWidth !== undefined ? mk.borderWidth : 3;
|
|
27860
27909
|
var g = markerGeometry(shape, size);
|
|
@@ -27865,22 +27914,29 @@ function smapCreateSdk(engine) {
|
|
|
27865
27914
|
// Opacity of the pin, its number and its badge together (the route map draws settled stops at .72).
|
|
27866
27915
|
var markerPaint = mk.opacity !== undefined ? { 'icon-opacity': valueExpr(mk.opacity, 1) } : undefined;
|
|
27867
27916
|
main = src + '-points';
|
|
27917
|
+
// From bakeZoom on (default 13) a pin's number is drawn into its own image, so an upper pin covers a lower
|
|
27918
|
+
// one completely. Further out, where thousands of pins can be in view, the numbers stay one layer above the
|
|
27919
|
+
// pins (an image per colour pair instead of per pin and number). bakeZoom: false keeps them separate.
|
|
27920
|
+
var plainPin = drawnImageId('pin', [shape, str(mk.fill, '#ffffff'), str(mk.border, color), String(bw), String(size)]);
|
|
27921
|
+
var bakeZoom = mk.text !== undefined && mk.bakeZoom !== false ? (mk.bakeZoom !== undefined ? mk.bakeZoom : 13) : null;
|
|
27922
|
+
var pinImage = bakeZoom === null ? plainPin : ['step', ['zoom'], plainPin, bakeZoom,
|
|
27923
|
+
drawnImageId('pinnum', [shape, str(mk.fill, '#ffffff'), str(mk.border, color), String(bw), String(size), str(mk.textColor, '#ffffff'), str(mk.text, '')])];
|
|
27868
27924
|
var markerSpecs = [];
|
|
27869
27925
|
var addMarker = function (layer) { markerSpecs.push(JSON.parse(JSON.stringify(layer))); add(layer); };
|
|
27870
27926
|
addMarker({
|
|
27871
27927
|
id: main, type: 'symbol', filter: only, paint: markerPaint,
|
|
27872
27928
|
layout: {
|
|
27873
|
-
'icon-image':
|
|
27874
|
-
'icon-anchor': shape === '
|
|
27929
|
+
'icon-image': pinImage,
|
|
27930
|
+
'icon-anchor': shape === 'pin' ? 'bottom' : 'center',
|
|
27875
27931
|
// The image has room for the shadow below the tip: the tip, not the image's edge, is at the position.
|
|
27876
|
-
'icon-offset': [0, shape === '
|
|
27932
|
+
'icon-offset': [0, shape === 'pin' ? PIN_PAD : 0], 'icon-size': scale,
|
|
27877
27933
|
'icon-allow-overlap': true, 'icon-ignore-placement': true,
|
|
27878
27934
|
},
|
|
27879
27935
|
});
|
|
27880
27936
|
if (mk.text !== undefined) {
|
|
27881
27937
|
var text = str(mk.text, '');
|
|
27882
27938
|
addMarker({
|
|
27883
|
-
id: src + '-numbers', type: 'symbol', filter: both(['!=', text, '']), minzoom: mk.textMinzoom, paint: markerPaint,
|
|
27939
|
+
id: src + '-numbers', type: 'symbol', filter: both(['!=', text, '']), minzoom: mk.textMinzoom, maxzoom: bakeZoom === null ? undefined : bakeZoom, paint: markerPaint,
|
|
27884
27940
|
layout: {
|
|
27885
27941
|
'icon-image': drawnImageId('num', [str(mk.textColor, '#ffffff'), String(size), text]),
|
|
27886
27942
|
'icon-offset': [0, -g.tipToHead], 'icon-size': scale, 'icon-allow-overlap': true, 'icon-ignore-placement': true,
|
|
@@ -27927,7 +27983,9 @@ function smapCreateSdk(engine) {
|
|
|
27927
27983
|
if (o.label) {
|
|
27928
27984
|
add({
|
|
27929
27985
|
id: src + '-labels', type: 'symbol', filter: only,
|
|
27930
|
-
layout:
|
|
27986
|
+
layout: o.labelPosition === 'right'
|
|
27987
|
+
? { 'text-field': ['to-string', ['get', o.label]], 'text-font': ['Noto Sans Regular'], 'text-size': 11, 'text-offset': [1.3, 0], 'text-anchor': 'left', 'text-optional': true, 'text-max-width': 12 }
|
|
27988
|
+
: { 'text-field': ['to-string', ['get', o.label]], 'text-font': ['Noto Sans Regular'], 'text-size': 12, 'text-offset': [0, 1.2], 'text-anchor': 'top', 'text-optional': true },
|
|
27931
27989
|
paint: { 'text-color': '#1f2937', 'text-halo-color': '#ffffff', 'text-halo-width': 1.4 },
|
|
27932
27990
|
});
|
|
27933
27991
|
}
|
|
@@ -28009,6 +28067,7 @@ function smapCreateSdk(engine) {
|
|
|
28009
28067
|
if (layer.filter === undefined) { delete layer.filter; }
|
|
28010
28068
|
if (layer.paint === undefined) { delete layer.paint; }
|
|
28011
28069
|
if (layer.minzoom === undefined) { delete layer.minzoom; }
|
|
28070
|
+
if (layer.maxzoom === undefined) { delete layer.maxzoom; }
|
|
28012
28071
|
m.addLayer(layer);
|
|
28013
28072
|
def.engineLayers.push(layer.id);
|
|
28014
28073
|
if (!top) { top = layer.id; }
|
package/dist/smap.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Generated by js/build.mjs from js/src (see SOURCE.json). Do not edit. */
|
|
2
|
-
/*! sMap Web SDK 1.0.
|
|
2
|
+
/*! sMap Web SDK 1.0.6. Bundles maplibre-gl 6.16.0 (BSD-3-Clause), see vendor-licenses.txt. */
|
|
3
3
|
|
|
4
4
|
var smapCore = null;
|
|
5
5
|
function smapCreateEngine() {
|
|
@@ -26872,7 +26872,7 @@ function smapCreateSdk(engine) {
|
|
|
26872
26872
|
})(typeof self !== 'undefined' ? self : this, function (engine) {
|
|
26873
26873
|
'use strict';
|
|
26874
26874
|
|
|
26875
|
-
var VERSION = '1.0.
|
|
26875
|
+
var VERSION = '1.0.6';
|
|
26876
26876
|
var FLAVORS = ['light', 'white', 'grayscale', 'dark', 'black'];
|
|
26877
26877
|
var BASEMAP_SOURCE = 'basemap';
|
|
26878
26878
|
var BUILDINGS_LAYER = 'smap-buildings-3d';
|
|
@@ -27027,7 +27027,7 @@ function smapCreateSdk(engine) {
|
|
|
27027
27027
|
// from the position (right of the round part, as the page's badge sits on the turned pin's corner).
|
|
27028
27028
|
function markerGeometry(shape, size) {
|
|
27029
27029
|
var k = size / 32;
|
|
27030
|
-
if (shape === 'circle') {
|
|
27030
|
+
if (shape === 'circle' || shape === 'vehicle') {
|
|
27031
27031
|
return { k: k, tipToHead: 0, badge: [size * 0.36, -size * 0.36] };
|
|
27032
27032
|
}
|
|
27033
27033
|
var half = size * SQRT1_2; // the centre of the round part, above the tip
|
|
@@ -27053,16 +27053,18 @@ function smapCreateSdk(engine) {
|
|
|
27053
27053
|
|
|
27054
27054
|
// Each draw function gets a 2D context already scaled to the pixel ratio and returns nothing; sizes are in pixels.
|
|
27055
27055
|
var IMAGE_KINDS = {
|
|
27056
|
-
// pin|shape|fill|border|borderWidth|size
|
|
27056
|
+
// pin|shape|fill|border|borderWidth|size (shape pin, circle, or vehicle: the route map's live position, a white
|
|
27057
|
+
// circle with a truck in the border colour)
|
|
27057
27058
|
pin: function (args) {
|
|
27058
27059
|
var shape = args[0], fill = args[1], border = args[2], bw = Number(args[3]), size = Number(args[4]);
|
|
27059
27060
|
var g = markerGeometry(shape, size);
|
|
27060
|
-
var reach = shape === '
|
|
27061
|
+
var reach = shape === 'pin' ? g.tipToHead : size / 2; // farthest the shape goes from its centre
|
|
27061
27062
|
var w = Math.ceil(2 * reach + 2 * PIN_PAD), h = w;
|
|
27062
27063
|
return {
|
|
27063
27064
|
width: w, height: h,
|
|
27064
27065
|
draw: function (ctx, ratio) {
|
|
27065
27066
|
var c = w / 2;
|
|
27067
|
+
if (shape === 'vehicle') { drawVehicle(ctx, ratio, c, size, border); return; }
|
|
27066
27068
|
ctx.save();
|
|
27067
27069
|
ctx.translate(c, c);
|
|
27068
27070
|
var s = size / 2;
|
|
@@ -27093,6 +27095,31 @@ function smapCreateSdk(engine) {
|
|
|
27093
27095
|
},
|
|
27094
27096
|
};
|
|
27095
27097
|
},
|
|
27098
|
+
// pinnum|shape|fill|border|borderWidth|size|textColor|text: a pin with its number drawn in, so a pin above covers a
|
|
27099
|
+
// pin below completely (used close up, where few pins are in view; further out the number is its own layer).
|
|
27100
|
+
pinnum: function (args, measure) {
|
|
27101
|
+
var pin = IMAGE_KINDS.pin(args.slice(0, 5));
|
|
27102
|
+
var size = Number(args[4]), color = args[5], text = args.slice(6).join('|');
|
|
27103
|
+
var px = 14 * size / 32, font = 'bold ' + px + 'px monospace';
|
|
27104
|
+
return {
|
|
27105
|
+
width: pin.width, height: pin.height,
|
|
27106
|
+
draw: function (ctx, ratio) {
|
|
27107
|
+
pin.draw(ctx, ratio);
|
|
27108
|
+
if (text === '') { return; }
|
|
27109
|
+
ctx.save();
|
|
27110
|
+
ctx.font = font;
|
|
27111
|
+
ctx.textAlign = 'center';
|
|
27112
|
+
ctx.textBaseline = 'middle';
|
|
27113
|
+
ctx.shadowColor = 'rgba(0,0,0,0.5)';
|
|
27114
|
+
ctx.shadowOffsetX = ratio;
|
|
27115
|
+
ctx.shadowOffsetY = ratio;
|
|
27116
|
+
ctx.shadowBlur = 2 * ratio;
|
|
27117
|
+
ctx.fillStyle = color;
|
|
27118
|
+
ctx.fillText(text, pin.width / 2, pin.height / 2 + 0.5);
|
|
27119
|
+
ctx.restore();
|
|
27120
|
+
},
|
|
27121
|
+
};
|
|
27122
|
+
},
|
|
27096
27123
|
// num|color|size|text (bold, with the route map's text shadow)
|
|
27097
27124
|
num: function (args, measure) {
|
|
27098
27125
|
var color = args[0], size = Number(args[1]), text = args.slice(2).join('|');
|
|
@@ -27372,6 +27399,27 @@ function smapCreateSdk(engine) {
|
|
|
27372
27399
|
};
|
|
27373
27400
|
|
|
27374
27401
|
// Draws an image the SDK named (IMAGE_PREFIX + kind|args) and adds it to the map; other names are left alone.
|
|
27402
|
+
// The live-position marker of the route map: a white circle (85%) with a truck in the driver colour.
|
|
27403
|
+
function drawVehicle(ctx, ratio, c, size, color) {
|
|
27404
|
+
var r = size / 2, k = size / 24;
|
|
27405
|
+
ctx.save();
|
|
27406
|
+
ctx.translate(c, c);
|
|
27407
|
+
ctx.shadowColor = 'rgba(0,0,0,0.5)';
|
|
27408
|
+
ctx.shadowBlur = 2 * ratio;
|
|
27409
|
+
ctx.beginPath(); ctx.arc(0, 0, r, 0, Math.PI * 2);
|
|
27410
|
+
ctx.fillStyle = 'rgba(255,255,255,0.85)'; ctx.fill();
|
|
27411
|
+
ctx.shadowColor = 'transparent';
|
|
27412
|
+
ctx.scale(k, k);
|
|
27413
|
+
ctx.fillStyle = color;
|
|
27414
|
+
// cargo box, cab and two wheels, about 14 x 10 px on a 24 px marker
|
|
27415
|
+
ctx.fillRect(-7, -5, 8.5, 7);
|
|
27416
|
+
roundedPath(ctx, 2.2, -2.6, 4.8, 4.6, [[1.4, 1.4], [0.6, 0.6], [0, 0], [0, 0]]); ctx.fill();
|
|
27417
|
+
ctx.beginPath(); ctx.arc(-4.2, 3.4, 1.9, 0, Math.PI * 2); ctx.arc(4.1, 3.4, 1.9, 0, Math.PI * 2); ctx.fill();
|
|
27418
|
+
ctx.fillStyle = 'rgba(255,255,255,0.85)';
|
|
27419
|
+
ctx.beginPath(); ctx.arc(-4.2, 3.4, 0.7, 0, Math.PI * 2); ctx.arc(4.1, 3.4, 0.7, 0, Math.PI * 2); ctx.fill();
|
|
27420
|
+
ctx.restore();
|
|
27421
|
+
}
|
|
27422
|
+
|
|
27375
27423
|
SMap.prototype._drawImage = function (id) {
|
|
27376
27424
|
if (typeof id !== 'string' || id.indexOf(IMAGE_PREFIX) !== 0) { return; }
|
|
27377
27425
|
var m = this.engine;
|
|
@@ -27552,7 +27600,7 @@ function smapCreateSdk(engine) {
|
|
|
27552
27600
|
if (hit.o.marker && popupOptions.offset === undefined && this._popupDefaults.offset === undefined) {
|
|
27553
27601
|
// Just above the pin as it is drawn now (its scale may follow the zoom).
|
|
27554
27602
|
var mk = hit.o.marker, size = mk.size || 32, k = scaleAt(mk.scale, m.getZoom ? m.getZoom() : 0);
|
|
27555
|
-
popupOptions.offset = mk.shape === 'circle' ? Math.round((size / 2) * k + 4) : Math.round((markerGeometry('pin', size).tipToHead + size / 2) * k + 2);
|
|
27603
|
+
popupOptions.offset = mk.shape === 'circle' || mk.shape === 'vehicle' ? Math.round((size / 2) * k + 4) : Math.round((markerGeometry('pin', size).tipToHead + size / 2) * k + 2);
|
|
27556
27604
|
}
|
|
27557
27605
|
// Above the pin, always (as on Superroute's route map); the map pans to make room instead of flipping it below.
|
|
27558
27606
|
if (hit.o.marker && popupOptions.anchor === undefined && this._popupDefaults.anchor === undefined) { popupOptions.anchor = 'bottom'; }
|
|
@@ -27819,6 +27867,7 @@ function smapCreateSdk(engine) {
|
|
|
27819
27867
|
// The engine refuses a filter key whose value is undefined (unclustered points have none).
|
|
27820
27868
|
if (layer.filter === undefined) { delete layer.filter; }
|
|
27821
27869
|
if (layer.minzoom === undefined) { delete layer.minzoom; }
|
|
27870
|
+
if (layer.maxzoom === undefined) { delete layer.maxzoom; }
|
|
27822
27871
|
if (layer.paint === undefined) { delete layer.paint; }
|
|
27823
27872
|
// A layer's own minzoom (a marker's textMinzoom / badgeMinzoom) never shows it before the layer's own range.
|
|
27824
27873
|
for (var k in range) { layer[k] = k === 'minzoom' && layer.minzoom !== undefined ? Math.max(layer.minzoom, range.minzoom) : range[k]; }
|
|
@@ -27856,7 +27905,7 @@ function smapCreateSdk(engine) {
|
|
|
27856
27905
|
// Pins like Superroute's route map, drawn on the GPU: one image per colour pair (and per number, per badge),
|
|
27857
27906
|
// made the first time a feature shows it. Numbers and badges are their own layers above the pins.
|
|
27858
27907
|
var mk = o.marker;
|
|
27859
|
-
var shape = mk.shape === 'circle'
|
|
27908
|
+
var shape = mk.shape === 'circle' || mk.shape === 'vehicle' ? mk.shape : 'pin';
|
|
27860
27909
|
var size = mk.size || 32;
|
|
27861
27910
|
var bw = mk.borderWidth !== undefined ? mk.borderWidth : 3;
|
|
27862
27911
|
var g = markerGeometry(shape, size);
|
|
@@ -27867,22 +27916,29 @@ function smapCreateSdk(engine) {
|
|
|
27867
27916
|
// Opacity of the pin, its number and its badge together (the route map draws settled stops at .72).
|
|
27868
27917
|
var markerPaint = mk.opacity !== undefined ? { 'icon-opacity': valueExpr(mk.opacity, 1) } : undefined;
|
|
27869
27918
|
main = src + '-points';
|
|
27919
|
+
// From bakeZoom on (default 13) a pin's number is drawn into its own image, so an upper pin covers a lower
|
|
27920
|
+
// one completely. Further out, where thousands of pins can be in view, the numbers stay one layer above the
|
|
27921
|
+
// pins (an image per colour pair instead of per pin and number). bakeZoom: false keeps them separate.
|
|
27922
|
+
var plainPin = drawnImageId('pin', [shape, str(mk.fill, '#ffffff'), str(mk.border, color), String(bw), String(size)]);
|
|
27923
|
+
var bakeZoom = mk.text !== undefined && mk.bakeZoom !== false ? (mk.bakeZoom !== undefined ? mk.bakeZoom : 13) : null;
|
|
27924
|
+
var pinImage = bakeZoom === null ? plainPin : ['step', ['zoom'], plainPin, bakeZoom,
|
|
27925
|
+
drawnImageId('pinnum', [shape, str(mk.fill, '#ffffff'), str(mk.border, color), String(bw), String(size), str(mk.textColor, '#ffffff'), str(mk.text, '')])];
|
|
27870
27926
|
var markerSpecs = [];
|
|
27871
27927
|
var addMarker = function (layer) { markerSpecs.push(JSON.parse(JSON.stringify(layer))); add(layer); };
|
|
27872
27928
|
addMarker({
|
|
27873
27929
|
id: main, type: 'symbol', filter: only, paint: markerPaint,
|
|
27874
27930
|
layout: {
|
|
27875
|
-
'icon-image':
|
|
27876
|
-
'icon-anchor': shape === '
|
|
27931
|
+
'icon-image': pinImage,
|
|
27932
|
+
'icon-anchor': shape === 'pin' ? 'bottom' : 'center',
|
|
27877
27933
|
// The image has room for the shadow below the tip: the tip, not the image's edge, is at the position.
|
|
27878
|
-
'icon-offset': [0, shape === '
|
|
27934
|
+
'icon-offset': [0, shape === 'pin' ? PIN_PAD : 0], 'icon-size': scale,
|
|
27879
27935
|
'icon-allow-overlap': true, 'icon-ignore-placement': true,
|
|
27880
27936
|
},
|
|
27881
27937
|
});
|
|
27882
27938
|
if (mk.text !== undefined) {
|
|
27883
27939
|
var text = str(mk.text, '');
|
|
27884
27940
|
addMarker({
|
|
27885
|
-
id: src + '-numbers', type: 'symbol', filter: both(['!=', text, '']), minzoom: mk.textMinzoom, paint: markerPaint,
|
|
27941
|
+
id: src + '-numbers', type: 'symbol', filter: both(['!=', text, '']), minzoom: mk.textMinzoom, maxzoom: bakeZoom === null ? undefined : bakeZoom, paint: markerPaint,
|
|
27886
27942
|
layout: {
|
|
27887
27943
|
'icon-image': drawnImageId('num', [str(mk.textColor, '#ffffff'), String(size), text]),
|
|
27888
27944
|
'icon-offset': [0, -g.tipToHead], 'icon-size': scale, 'icon-allow-overlap': true, 'icon-ignore-placement': true,
|
|
@@ -27929,7 +27985,9 @@ function smapCreateSdk(engine) {
|
|
|
27929
27985
|
if (o.label) {
|
|
27930
27986
|
add({
|
|
27931
27987
|
id: src + '-labels', type: 'symbol', filter: only,
|
|
27932
|
-
layout:
|
|
27988
|
+
layout: o.labelPosition === 'right'
|
|
27989
|
+
? { 'text-field': ['to-string', ['get', o.label]], 'text-font': ['Noto Sans Regular'], 'text-size': 11, 'text-offset': [1.3, 0], 'text-anchor': 'left', 'text-optional': true, 'text-max-width': 12 }
|
|
27990
|
+
: { 'text-field': ['to-string', ['get', o.label]], 'text-font': ['Noto Sans Regular'], 'text-size': 12, 'text-offset': [0, 1.2], 'text-anchor': 'top', 'text-optional': true },
|
|
27933
27991
|
paint: { 'text-color': '#1f2937', 'text-halo-color': '#ffffff', 'text-halo-width': 1.4 },
|
|
27934
27992
|
});
|
|
27935
27993
|
}
|
|
@@ -28011,6 +28069,7 @@ function smapCreateSdk(engine) {
|
|
|
28011
28069
|
if (layer.filter === undefined) { delete layer.filter; }
|
|
28012
28070
|
if (layer.paint === undefined) { delete layer.paint; }
|
|
28013
28071
|
if (layer.minzoom === undefined) { delete layer.minzoom; }
|
|
28072
|
+
if (layer.maxzoom === undefined) { delete layer.maxzoom; }
|
|
28014
28073
|
m.addLayer(layer);
|
|
28015
28074
|
def.engineLayers.push(layer.id);
|
|
28016
28075
|
if (!top) { top = layer.id; }
|
|
@@ -28070,7 +28129,7 @@ function SMapMap(options) {
|
|
|
28070
28129
|
SMapMap.prototype = core.Map.prototype;
|
|
28071
28130
|
return new core.Map(options);
|
|
28072
28131
|
}
|
|
28073
|
-
var smapVersion = "1.0.
|
|
28132
|
+
var smapVersion = "1.0.6";
|
|
28074
28133
|
var smapStyles = ['light', 'white', 'grayscale', 'dark', 'black'];
|
|
28075
28134
|
/** The bundled rendering engine, for anything the SDK does not wrap (loaded on the first call). */
|
|
28076
28135
|
function smapGetEngine() { return smapLoad().engine; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superrouteca/smap",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "sMap for the web: maps from Superroute's sMap service, the Web SDK (map view) and the JS client (tokens, nearest node, styles, tiles).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Goodneo Solutions",
|
package/types/smap.d.cts
CHANGED
|
@@ -104,7 +104,7 @@ export type StyleValue<T = string> = T | { property: string; default?: T } | unk
|
|
|
104
104
|
/** Pins like Superroute's route map, drawn on the GPU (one image per colour pair, made when first shown). */
|
|
105
105
|
export interface MarkerOptions {
|
|
106
106
|
/** `pin` (default: a teardrop whose tip is at the position) or `circle` (centred on it). */
|
|
107
|
-
shape?: 'pin' | 'circle';
|
|
107
|
+
shape?: 'pin' | 'circle' | 'vehicle';
|
|
108
108
|
/** Inside colour (default white). */
|
|
109
109
|
fill?: StyleValue;
|
|
110
110
|
/** Border colour (default the layer's `color`). */
|
|
@@ -124,6 +124,8 @@ export interface MarkerOptions {
|
|
|
124
124
|
scale?: number | unknown[];
|
|
125
125
|
/** The pin under the pointer comes to the front (default true). */
|
|
126
126
|
hoverRaise?: boolean;
|
|
127
|
+
/** From this zoom on (default 13) the number is drawn into the pin, so an upper pin covers a lower one completely; false keeps it a separate layer. */
|
|
128
|
+
bakeZoom?: number | false;
|
|
127
129
|
/**
|
|
128
130
|
* Pins piled up under a click (default on): with `threshold` (4) or more within `radius` (12 px) the map zooms in by
|
|
129
131
|
* `zoomBy` (2) up to `maxZoom` (17); close up, or for pins at one spot, a chooser lists them (`label(properties)`).
|
|
@@ -153,6 +155,8 @@ export interface PointOptions extends CommonLayerOptions {
|
|
|
153
155
|
iconAnchor?: string;
|
|
154
156
|
/** The property written under each point. */
|
|
155
157
|
label?: string;
|
|
158
|
+
/** Where the label sits: below the point (default) or 'right' of it. */
|
|
159
|
+
labelPosition?: 'below' | 'right';
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
export interface LineOptions extends CommonLayerOptions {
|
package/types/smap.d.mts
CHANGED
|
@@ -104,7 +104,7 @@ export type StyleValue<T = string> = T | { property: string; default?: T } | unk
|
|
|
104
104
|
/** Pins like Superroute's route map, drawn on the GPU (one image per colour pair, made when first shown). */
|
|
105
105
|
export interface MarkerOptions {
|
|
106
106
|
/** `pin` (default: a teardrop whose tip is at the position) or `circle` (centred on it). */
|
|
107
|
-
shape?: 'pin' | 'circle';
|
|
107
|
+
shape?: 'pin' | 'circle' | 'vehicle';
|
|
108
108
|
/** Inside colour (default white). */
|
|
109
109
|
fill?: StyleValue;
|
|
110
110
|
/** Border colour (default the layer's `color`). */
|
|
@@ -124,6 +124,8 @@ export interface MarkerOptions {
|
|
|
124
124
|
scale?: number | unknown[];
|
|
125
125
|
/** The pin under the pointer comes to the front (default true). */
|
|
126
126
|
hoverRaise?: boolean;
|
|
127
|
+
/** From this zoom on (default 13) the number is drawn into the pin, so an upper pin covers a lower one completely; false keeps it a separate layer. */
|
|
128
|
+
bakeZoom?: number | false;
|
|
127
129
|
/**
|
|
128
130
|
* Pins piled up under a click (default on): with `threshold` (4) or more within `radius` (12 px) the map zooms in by
|
|
129
131
|
* `zoomBy` (2) up to `maxZoom` (17); close up, or for pins at one spot, a chooser lists them (`label(properties)`).
|
|
@@ -153,6 +155,8 @@ export interface PointOptions extends CommonLayerOptions {
|
|
|
153
155
|
iconAnchor?: string;
|
|
154
156
|
/** The property written under each point. */
|
|
155
157
|
label?: string;
|
|
158
|
+
/** Where the label sits: below the point (default) or 'right' of it. */
|
|
159
|
+
labelPosition?: 'below' | 'right';
|
|
156
160
|
}
|
|
157
161
|
|
|
158
162
|
export interface LineOptions extends CommonLayerOptions {
|