Skip to content

Commit b69cf4b

Browse files
authored
Merge pull request #4006 from plotly/mapbox-raster-layer
Add support for raster and image mapbox layers
2 parents f5bc2e4 + 0b17b62 commit b69cf4b

File tree

6 files changed

+122
-12
lines changed

6 files changed

+122
-12
lines changed

src/plots/mapbox/layers.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ function isVisible(opts) {
131131

132132
return opts.visible && (
133133
Lib.isPlainObject(source) ||
134-
(typeof source === 'string' && source.length > 0)
134+
((typeof source === 'string' || Array.isArray(source)) && source.length > 0)
135135
);
136136
}
137137

@@ -193,7 +193,10 @@ function convertOpts(opts) {
193193
break;
194194
}
195195

196-
return { layout: layout, paint: paint };
196+
return {
197+
layout: layout,
198+
paint: paint
199+
};
197200
}
198201

199202
function convertSourceOpts(opts) {
@@ -206,9 +209,16 @@ function convertSourceOpts(opts) {
206209
field = 'data';
207210
} else if(sourceType === 'vector') {
208211
field = typeof source === 'string' ? 'url' : 'tiles';
212+
} else if(sourceType === 'raster') {
213+
field = 'tiles';
214+
sourceOpts.tileSize = 256;
215+
} else if(sourceType === 'image') {
216+
field = 'url';
217+
sourceOpts.coordinates = opts.coordinates;
209218
}
210219

211220
sourceOpts[field] = source;
221+
212222
return sourceOpts;
213223
}
214224

src/plots/mapbox/layout_attributes.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,11 @@ var attrs = module.exports = overrideAll({
102102
},
103103
sourcetype: {
104104
valType: 'enumerated',
105-
values: ['geojson', 'vector'],
105+
values: ['geojson', 'vector', 'raster', 'image'],
106106
dflt: 'geojson',
107107
role: 'info',
108108
description: [
109-
'Sets the source type for this layer.',
110-
'Support for *raster*, *image* and *video* source types is coming soon.'
109+
'Sets the source type for this layer.'
111110
].join(' ')
112111
},
113112

@@ -134,7 +133,7 @@ var attrs = module.exports = overrideAll({
134133

135134
type: {
136135
valType: 'enumerated',
137-
values: ['circle', 'line', 'fill', 'symbol'],
136+
values: ['circle', 'line', 'fill', 'symbol', 'raster'],
138137
dflt: 'circle',
139138
role: 'info',
140139
description: [
@@ -145,6 +144,17 @@ var attrs = module.exports = overrideAll({
145144
].join(' ')
146145
},
147146

147+
coordinates: {
148+
valType: 'any',
149+
role: 'info',
150+
description: [
151+
'Sets the coordinates array contains [longitude, latitude] pairs',
152+
'for the image corners listed in clockwise order:',
153+
'top left, top right, bottom right, bottom left.',
154+
'Only has an effect for *image* `sourcetype`.'
155+
].join(' ')
156+
},
157+
148158
// attributes shared between all types
149159
below: {
150160
valType: 'string',

src/plots/mapbox/layout_defaults.js

+18-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

1211
var Lib = require('../../lib');
@@ -52,12 +51,27 @@ function handleLayerDefaults(layerIn, layerOut) {
5251
var visible = coerce('visible');
5352
if(visible) {
5453
var sourceType = coerce('sourcetype');
54+
var mustBeRasterLayer = sourceType === 'raster' || sourceType === 'image';
55+
5556
coerce('source');
5657

57-
if(sourceType === 'vector') coerce('sourcelayer');
58+
if(sourceType === 'vector') {
59+
coerce('sourcelayer');
60+
}
61+
62+
if(sourceType === 'image') {
63+
coerce('coordinates');
64+
}
65+
66+
var typeDflt;
67+
if(mustBeRasterLayer) typeDflt = 'raster';
5868

59-
// maybe add smart default based off GeoJSON geometry?
60-
var type = coerce('type');
69+
var type = coerce('type', typeDflt);
70+
71+
if(mustBeRasterLayer && type !== 'raster') {
72+
type = layerOut.type = 'raster';
73+
Lib.log('Source types *raster* and *image* must drawn *raster* layer type.');
74+
}
6175

6276
coerce('below');
6377
coerce('color');
41.6 KB
Loading

test/image/mocks/mapbox_layers.json

+32-2
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@
2121
"#7570b3"
2222
]
2323
}
24+
},
25+
{
26+
"type": "scattermapbox",
27+
"subplot": "mapbox2"
2428
}
2529
],
2630
"layout": {
2731
"mapbox": {
32+
"domain": {"x": [0, 0.48], "y": [0, 1]},
2833
"style": "light",
2934
"center": {
3035
"lon": -73.59194521800514,
@@ -547,8 +552,33 @@
547552
}
548553
]
549554
},
555+
556+
"mapbox2": {
557+
"domain": {"x": [0.52, 1], "y": [0, 1]},
558+
"style": "mapbox://styles/mapbox/light-v10",
559+
"zoom": 4.5,
560+
"center": {"lon": -74.5, "lat": 42},
561+
"layers": [
562+
{
563+
"sourcetype": "raster",
564+
"source": [
565+
"https://img.nj.gov/imagerywms/Natural2015?bbox={bbox-epsg-3857}&format=image/png&service=WMS&version=1.1.1&request=GetMap&srs=EPSG:3857&transparent=true&width=256&height=256&layers=Natural2015"
566+
],
567+
"below": "aeroway-line"
568+
},
569+
{
570+
"sourcetype": "image",
571+
"coordinates": [
572+
[-80.425, 46.437],
573+
[-71.516, 46.437],
574+
[-71.516, 37.936],
575+
[-80.425, 37.936]
576+
],
577+
"source": "https://docs.mapbox.com/mapbox-gl-js/assets/radar.gif"
578+
}
579+
]
580+
},
550581
"height": 450,
551-
"width": 1100,
552-
"autosize": true
582+
"width": 900
553583
}
554584
}

test/jasmine/tests/mapbox_test.js

+46
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,52 @@ describe('mapbox defaults', function() {
184184
expect(layoutOut.mapbox.layers[3].circle).toBeUndefined();
185185
});
186186

187+
it('should not allow to set layer type other than *raster* for sourcetype value *raster* and *image*', function() {
188+
spyOn(Lib, 'log');
189+
190+
layoutIn = {
191+
mapbox: {
192+
layers: [{
193+
sourcetype: 'raster',
194+
source: 'url',
195+
type: 'circle'
196+
}, {
197+
sourcetype: 'image',
198+
source: 'url',
199+
type: 'fill'
200+
}]
201+
}
202+
};
203+
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
204+
205+
expect(Lib.log).toHaveBeenCalledTimes(2);
206+
expect(Lib.log).toHaveBeenCalledWith('Source types *raster* and *image* must drawn *raster* layer type.');
207+
208+
expect(layoutOut.mapbox.layers[0].type).toBe('raster');
209+
expect(layoutOut.mapbox.layers[1].type).toBe('raster');
210+
});
211+
212+
it('should default layer with sourcetype *raster* and *image* to type *raster', function() {
213+
spyOn(Lib, 'log');
214+
215+
layoutIn = {
216+
mapbox: {
217+
layers: [{
218+
sourcetype: 'raster',
219+
source: 'url'
220+
}, {
221+
sourcetype: 'image',
222+
source: 'url'
223+
}]
224+
}
225+
};
226+
supplyLayoutDefaults(layoutIn, layoutOut, fullData);
227+
228+
expect(Lib.log).toHaveBeenCalledTimes(0);
229+
expect(layoutOut.mapbox.layers[0].type).toBe('raster');
230+
expect(layoutOut.mapbox.layers[1].type).toBe('raster');
231+
});
232+
187233
it('should set *layout.dragmode* to pan while zoom is not available', function() {
188234
var gd = {
189235
data: fullData,

0 commit comments

Comments
 (0)