Skip to content

Commit 4770657

Browse files
committed
bring back mapbox files
1 parent 649122e commit 4770657

35 files changed

+4365
-0
lines changed

lib/choroplethmapbox.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = require('../src/traces/choroplethmapbox');

lib/densitymapbox.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = require('../src/traces/densitymapbox');

lib/index-mapbox.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
var Plotly = require('./core');
4+
5+
Plotly.register([
6+
// traces
7+
require('./scattermapbox'),
8+
require('./choroplethmapbox'),
9+
require('./densitymapbox'),
10+
11+
// transforms
12+
require('./aggregate'),
13+
require('./filter'),
14+
require('./groupby'),
15+
require('./sort'),
16+
17+
// components
18+
require('./calendars'),
19+
]);
20+
21+
module.exports = Plotly;

lib/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ Plotly.register([
3636
require('./heatmapgl'),
3737
require('./parcoords'),
3838
require('./parcats'),
39+
require('./scattermapbox'),
40+
require('./choroplethmapbox'),
41+
require('./densitymapbox'),
3942
require('./scattermapnew'),
4043
require('./choroplethmapnew'),
4144
require('./densitymapnew'),

lib/scattermapbox.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = require('../src/traces/scattermapbox');

src/plots/mapbox/constants.js

Lines changed: 255 additions & 0 deletions
Large diffs are not rendered by default.

src/plots/mapbox/convert_text_opts.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'use strict';
2+
3+
var Lib = require('../../lib');
4+
5+
/**
6+
* Convert plotly.js 'textposition' to mapbox-gl 'anchor' and 'offset'
7+
* (with the help of the icon size).
8+
*
9+
* @param {string} textpostion : plotly.js textposition value
10+
* @param {number} iconSize : plotly.js icon size (e.g. marker.size for traces)
11+
*
12+
* @return {object}
13+
* - anchor
14+
* - offset
15+
*/
16+
module.exports = function convertTextOpts(textposition, iconSize) {
17+
var parts = textposition.split(' ');
18+
var vPos = parts[0];
19+
var hPos = parts[1];
20+
21+
// ballpack values
22+
var factor = Lib.isArrayOrTypedArray(iconSize) ? Lib.mean(iconSize) : iconSize;
23+
var xInc = 0.5 + (factor / 100);
24+
var yInc = 1.5 + (factor / 100);
25+
26+
var anchorVals = ['', ''];
27+
var offset = [0, 0];
28+
29+
switch(vPos) {
30+
case 'top':
31+
anchorVals[0] = 'top';
32+
offset[1] = -yInc;
33+
break;
34+
case 'bottom':
35+
anchorVals[0] = 'bottom';
36+
offset[1] = yInc;
37+
break;
38+
}
39+
40+
switch(hPos) {
41+
case 'left':
42+
anchorVals[1] = 'right';
43+
offset[0] = -xInc;
44+
break;
45+
case 'right':
46+
anchorVals[1] = 'left';
47+
offset[0] = xInc;
48+
break;
49+
}
50+
51+
// Mapbox text-anchor must be one of:
52+
// center, left, right, top, bottom,
53+
// top-left, top-right, bottom-left, bottom-right
54+
55+
var anchor;
56+
if(anchorVals[0] && anchorVals[1]) anchor = anchorVals.join('-');
57+
else if(anchorVals[0]) anchor = anchorVals[0];
58+
else if(anchorVals[1]) anchor = anchorVals[1];
59+
else anchor = 'center';
60+
61+
return { anchor: anchor, offset: offset };
62+
};

src/plots/mapbox/index.js

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
'use strict';
2+
3+
var mapboxgl = require('@plotly/mapbox-gl/dist/mapbox-gl-unminified');
4+
5+
var Lib = require('../../lib');
6+
var strTranslate = Lib.strTranslate;
7+
var strScale = Lib.strScale;
8+
var getSubplotCalcData = require('../../plots/get_data').getSubplotCalcData;
9+
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
10+
var d3 = require('@plotly/d3');
11+
var Drawing = require('../../components/drawing');
12+
var svgTextUtils = require('../../lib/svg_text_utils');
13+
14+
var Mapbox = require('./mapbox');
15+
16+
var MAPBOX = 'mapbox';
17+
18+
var constants = exports.constants = require('./constants');
19+
20+
exports.name = MAPBOX;
21+
22+
exports.attr = 'subplot';
23+
24+
exports.idRoot = MAPBOX;
25+
26+
exports.idRegex = exports.attrRegex = Lib.counterRegex(MAPBOX);
27+
28+
exports.attributes = {
29+
subplot: {
30+
valType: 'subplotid',
31+
dflt: 'mapbox',
32+
editType: 'calc',
33+
description: [
34+
'Sets a reference between this trace\'s data coordinates and',
35+
'a mapbox subplot.',
36+
'If *mapbox* (the default value), the data refer to `layout.mapbox`.',
37+
'If *mapbox2*, the data refer to `layout.mapbox2`, and so on.'
38+
].join(' ')
39+
}
40+
};
41+
42+
exports.layoutAttributes = require('./layout_attributes');
43+
44+
exports.supplyLayoutDefaults = require('./layout_defaults');
45+
46+
exports.plot = function plot(gd) {
47+
var fullLayout = gd._fullLayout;
48+
var calcData = gd.calcdata;
49+
var mapboxIds = fullLayout._subplots[MAPBOX];
50+
51+
if(mapboxgl.version !== constants.requiredVersion) {
52+
throw new Error(constants.wrongVersionErrorMsg);
53+
}
54+
55+
var accessToken = findAccessToken(gd, mapboxIds);
56+
mapboxgl.accessToken = accessToken;
57+
58+
for(var i = 0; i < mapboxIds.length; i++) {
59+
var id = mapboxIds[i];
60+
var subplotCalcData = getSubplotCalcData(calcData, MAPBOX, id);
61+
var opts = fullLayout[id];
62+
var mapbox = opts._subplot;
63+
64+
if(!mapbox) {
65+
mapbox = new Mapbox(gd, id);
66+
fullLayout[id]._subplot = mapbox;
67+
}
68+
69+
if(!mapbox.viewInitial) {
70+
mapbox.viewInitial = {
71+
center: Lib.extendFlat({}, opts.center),
72+
zoom: opts.zoom,
73+
bearing: opts.bearing,
74+
pitch: opts.pitch
75+
};
76+
}
77+
78+
mapbox.plot(subplotCalcData, fullLayout, gd._promises);
79+
}
80+
};
81+
82+
exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
83+
var oldMapboxKeys = oldFullLayout._subplots[MAPBOX] || [];
84+
85+
for(var i = 0; i < oldMapboxKeys.length; i++) {
86+
var oldMapboxKey = oldMapboxKeys[i];
87+
88+
if(!newFullLayout[oldMapboxKey] && !!oldFullLayout[oldMapboxKey]._subplot) {
89+
oldFullLayout[oldMapboxKey]._subplot.destroy();
90+
}
91+
}
92+
};
93+
94+
exports.toSVG = function(gd) {
95+
var fullLayout = gd._fullLayout;
96+
var subplotIds = fullLayout._subplots[MAPBOX];
97+
var size = fullLayout._size;
98+
99+
for(var i = 0; i < subplotIds.length; i++) {
100+
var opts = fullLayout[subplotIds[i]];
101+
var domain = opts.domain;
102+
var mapbox = opts._subplot;
103+
104+
var imageData = mapbox.toImage('png');
105+
var image = fullLayout._glimages.append('svg:image');
106+
107+
image.attr({
108+
xmlns: xmlnsNamespaces.svg,
109+
'xlink:href': imageData,
110+
x: size.l + size.w * domain.x[0],
111+
y: size.t + size.h * (1 - domain.y[1]),
112+
width: size.w * (domain.x[1] - domain.x[0]),
113+
height: size.h * (domain.y[1] - domain.y[0]),
114+
preserveAspectRatio: 'none'
115+
});
116+
117+
var subplotDiv = d3.select(opts._subplot.div);
118+
119+
// Append logo if visible
120+
var hidden = subplotDiv.select('.mapboxgl-ctrl-logo').node().offsetParent === null;
121+
if(!hidden) {
122+
var logo = fullLayout._glimages.append('g');
123+
logo.attr('transform', strTranslate(size.l + size.w * domain.x[0] + 10, size.t + size.h * (1 - domain.y[0]) - 31));
124+
logo.append('path')
125+
.attr('d', constants.mapboxLogo.path0)
126+
.style({
127+
opacity: 0.9,
128+
fill: '#ffffff',
129+
'enable-background': 'new'
130+
});
131+
132+
logo.append('path')
133+
.attr('d', constants.mapboxLogo.path1)
134+
.style('opacity', 0.35)
135+
.style('enable-background', 'new');
136+
137+
logo.append('path')
138+
.attr('d', constants.mapboxLogo.path2)
139+
.style('opacity', 0.35)
140+
.style('enable-background', 'new');
141+
142+
logo.append('polygon')
143+
.attr('points', constants.mapboxLogo.polygon)
144+
.style({
145+
opacity: 0.9,
146+
fill: '#ffffff',
147+
'enable-background': 'new'
148+
});
149+
}
150+
151+
// Add attributions
152+
var attributions = subplotDiv
153+
.select('.mapboxgl-ctrl-attrib').text()
154+
.replace('Improve this map', '');
155+
156+
var attributionGroup = fullLayout._glimages.append('g');
157+
158+
var attributionText = attributionGroup.append('text');
159+
attributionText
160+
.text(attributions)
161+
.classed('static-attribution', true)
162+
.attr({
163+
'font-size': 12,
164+
'font-family': 'Arial',
165+
color: 'rgba(0, 0, 0, 0.75)',
166+
'text-anchor': 'end',
167+
'data-unformatted': attributions
168+
});
169+
170+
var bBox = Drawing.bBox(attributionText.node());
171+
172+
// Break into multiple lines twice larger than domain
173+
var maxWidth = size.w * (domain.x[1] - domain.x[0]);
174+
if((bBox.width > maxWidth / 2)) {
175+
var multilineAttributions = attributions.split('|').join('<br>');
176+
attributionText
177+
.text(multilineAttributions)
178+
.attr('data-unformatted', multilineAttributions)
179+
.call(svgTextUtils.convertToTspans, gd);
180+
181+
bBox = Drawing.bBox(attributionText.node());
182+
}
183+
attributionText.attr('transform', strTranslate(-3, -bBox.height + 8));
184+
185+
// Draw white rectangle behind text
186+
attributionGroup
187+
.insert('rect', '.static-attribution')
188+
.attr({
189+
x: -bBox.width - 6,
190+
y: -bBox.height - 3,
191+
width: bBox.width + 6,
192+
height: bBox.height + 3,
193+
fill: 'rgba(255, 255, 255, 0.75)'
194+
});
195+
196+
// Scale down if larger than domain
197+
var scaleRatio = 1;
198+
if((bBox.width + 6) > maxWidth) scaleRatio = maxWidth / (bBox.width + 6);
199+
200+
var offset = [(size.l + size.w * domain.x[1]), (size.t + size.h * (1 - domain.y[0]))];
201+
attributionGroup.attr('transform', strTranslate(offset[0], offset[1]) + strScale(scaleRatio));
202+
}
203+
};
204+
205+
// N.B. mapbox-gl only allows one accessToken to be set per page:
206+
// https://github.com/mapbox/mapbox-gl-js/issues/6331
207+
function findAccessToken(gd, mapboxIds) {
208+
var fullLayout = gd._fullLayout;
209+
var context = gd._context;
210+
211+
// special case for Mapbox Atlas users
212+
if(context.mapboxAccessToken === '') return '';
213+
214+
var tokensUseful = [];
215+
var tokensListed = [];
216+
var hasOneSetMapboxStyle = false;
217+
var wontWork = false;
218+
219+
// Take the first token we find in a mapbox subplot.
220+
// These default to the context value but may be overridden.
221+
for(var i = 0; i < mapboxIds.length; i++) {
222+
var opts = fullLayout[mapboxIds[i]];
223+
var token = opts.accesstoken;
224+
225+
if(isStyleRequireAccessToken(opts.style)) {
226+
if(token) {
227+
Lib.pushUnique(tokensUseful, token);
228+
} else {
229+
if(isStyleRequireAccessToken(opts._input.style)) {
230+
Lib.error('Uses Mapbox map style, but did not set an access token.');
231+
hasOneSetMapboxStyle = true;
232+
}
233+
wontWork = true;
234+
}
235+
}
236+
237+
if(token) {
238+
Lib.pushUnique(tokensListed, token);
239+
}
240+
}
241+
242+
if(wontWork) {
243+
var msg = hasOneSetMapboxStyle ?
244+
constants.noAccessTokenErrorMsg :
245+
constants.missingStyleErrorMsg;
246+
Lib.error(msg);
247+
throw new Error(msg);
248+
}
249+
250+
if(tokensUseful.length) {
251+
if(tokensUseful.length > 1) {
252+
Lib.warn(constants.multipleTokensErrorMsg);
253+
}
254+
return tokensUseful[0];
255+
} else {
256+
if(tokensListed.length) {
257+
Lib.log([
258+
'Listed mapbox access token(s)', tokensListed.join(','),
259+
'but did not use a Mapbox map style, ignoring token(s).'
260+
].join(' '));
261+
}
262+
return '';
263+
}
264+
}
265+
266+
function isStyleRequireAccessToken(s) {
267+
return typeof s === 'string' && (
268+
constants.styleValuesMapbox.indexOf(s) !== -1 ||
269+
s.indexOf('mapbox://') === 0 ||
270+
s.indexOf('stamen') === 0
271+
);
272+
}
273+
274+
exports.updateFx = function(gd) {
275+
var fullLayout = gd._fullLayout;
276+
var subplotIds = fullLayout._subplots[MAPBOX];
277+
278+
for(var i = 0; i < subplotIds.length; i++) {
279+
var subplotObj = fullLayout[subplotIds[i]]._subplot;
280+
subplotObj.updateFx(fullLayout);
281+
}
282+
};

0 commit comments

Comments
 (0)