Skip to content

Add support for mapbox style JSON #795

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib/coerce.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ exports.valObjects = {
any: {
description: 'Any type.',
requiredOpts: [],
otherOpts: ['dflt'],
otherOpts: ['dflt', 'values'],
coerceFunction: function(v, propOut, dflt) {
if(v === undefined) propOut.set(dflt);
else propOut.set(v);
Expand Down
5 changes: 3 additions & 2 deletions src/plots/mapbox/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ module.exports = {
].join(' ')
},
style: {
valType: 'string',
valType: 'any',
values: ['basic', 'streets', 'outdoors', 'light', 'dark', 'satellite', 'satellite-streets'],
dflt: 'basic',
role: 'style',
description: [
'Sets the Mapbox map style.',
'Either input the defaults Mapbox names or the URL to a custom style.'
'Either input one of the default Mapbox style names or the URL to a custom style',
'or a valid Mapbox style JSON.'
].join(' ')
},

Expand Down
49 changes: 33 additions & 16 deletions src/plots/mapbox/mapbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function Mapbox(opts) {
// state variables used to infer how and what to update
this.map = null;
this.accessToken = null;
this.styleUrl = null;
this.styleObj = null;
this.traceHash = {};
this.layerList = [];
}
Expand All @@ -64,7 +64,7 @@ proto.plot = function(calcData, fullLayout, promises) {
if(self.map && (opts.accesstoken !== self.accessToken)) {
self.map.remove();
self.map = null;
self.styleUrl = null;
self.styleObj = null;
self.traceHash = [];
self.layerList = {};
}
Expand All @@ -90,16 +90,17 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
gd = self.gd,
opts = self.opts;

// mapbox doesn't have a way to get the current style URL; do it ourselves
var styleUrl = self.styleUrl = convertStyleUrl(opts.style);
// store style id and URL or object
var styleObj = self.styleObj = getStyleObj(opts.style);

// store access token associated with this map
self.accessToken = opts.accesstoken;

// create the map!
var map = self.map = new mapboxgl.Map({
container: self.div,

style: styleUrl,
style: styleObj.style,
center: convertCenter(opts.center),
zoom: opts.zoom,
bearing: opts.bearing,
Expand Down Expand Up @@ -172,11 +173,11 @@ proto.updateMap = function(calcData, fullLayout, resolve, reject) {

self.rejectOnError(reject);

var styleUrl = convertStyleUrl(self.opts.style);
var styleObj = getStyleObj(self.opts.style);

if(self.styleUrl !== styleUrl) {
self.styleUrl = styleUrl;
map.setStyle(styleUrl);
if(self.styleObj.id !== styleObj.id) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @plotly/frontend simply mutating a mapbox style JSON won't trigger an update. Mapbox style JSONs are assumed to be constant unless their id change.

self.styleObj = styleObj;
map.setStyle(styleObj.style);

map.style.once('load', function() {

Expand Down Expand Up @@ -402,16 +403,32 @@ proto.getView = function() {
};
};

function convertStyleUrl(style) {
var styleValues = layoutAttributes.style.values;
function getStyleObj(val) {
var styleValues = layoutAttributes.style.values,
styleDflt = layoutAttributes.style.dflt,
styleObj = {};

// if style is part of the 'official' mapbox values,
// add URL prefix and suffix
if(styleValues.indexOf(style) !== -1) {
return constants.styleUrlPrefix + style + '-' + constants.styleUrlSuffix;
if(Lib.isPlainObject(val)) {
styleObj.id = val.id;
styleObj.style = val;
}
else if(typeof val === 'string') {
styleObj.id = val;
styleObj.style = (styleValues.indexOf(val) !== -1) ?
convertStyleVal(val) :
val;
}
else {
styleObj.id = styleDflt;
styleObj.style = convertStyleVal(styleDflt);
}

return styleObj;
}

return style;
// if style is part of the 'official' mapbox values, add URL prefix and suffix
function convertStyleVal(val) {
return constants.styleUrlPrefix + val + '-' + constants.styleUrlSuffix;
}

function convertCenter(center) {
Expand Down
18 changes: 18 additions & 0 deletions test/jasmine/tests/mapbox_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,24 @@ describe('mapbox defaults', function() {
expect(layoutOut.mapbox._input).toBe(mapbox);
});

it('should accept both string and object style', function() {
var mapboxStyleJSON = {
id: 'cdsa213wqdsa',
owner: 'johnny'
};

layoutIn = {
mapbox: { style: 'light' },
mapbox2: { style: mapboxStyleJSON }
};

fullData.push({ type: 'scattermapbox', subplot: 'mapbox2' });

supplyLayoutDefaults(layoutIn, layoutOut, fullData);
expect(layoutOut.mapbox.style).toEqual('light');
expect(layoutOut.mapbox2.style).toBe(mapboxStyleJSON);
});

it('should fill layer containers', function() {
layoutIn = {
mapbox: {
Expand Down