Skip to content

Commit 51fa1ea

Browse files
committed
add 'symbol' layer type
1 parent 1620e61 commit 51fa1ea

File tree

5 files changed

+115
-26
lines changed

5 files changed

+115
-26
lines changed

src/plots/mapbox/layers.js

+47-21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
'use strict';
1111

1212
var Lib = require('../../lib');
13+
var convertTextOpts = require('./convert_text_opts');
1314

1415

1516
function MapboxLayer(mapbox, index) {
@@ -46,14 +47,17 @@ proto.update = function update(opts) {
4647

4748
proto.needsNewSource = function(opts) {
4849

49-
// for some reason changing layer to 'fill' w/o changing the source
50-
// throws an exception in mapbox-gl 0.18
51-
var changesToFill = (this.layerType !== 'fill' && opts.type === 'fill');
50+
// for some reason changing layer to 'fill' or 'symbol'
51+
// w/o changing the source throws an exception in mapbox-gl 0.18
52+
53+
var changesToFill = (this.layerType !== 'fill' && opts.type === 'fill'),
54+
changesToSymbol = (this.layerType !== 'symbol' && opts.type === 'symbol');
5255

5356
return (
5457
this.sourceType !== opts.sourcetype ||
5558
this.source !== opts.source ||
56-
changesToFill
59+
changesToFill ||
60+
changesToSymbol
5761
);
5862
};
5963

@@ -101,10 +105,11 @@ proto.updateLayer = function(opts) {
101105
};
102106

103107
proto.updateStyle = function(opts) {
104-
var paintOpts = convertPaintOpts(opts);
108+
var convertedOpts = convertOpts(opts);
105109

106110
if(isVisible(opts)) {
107-
this.mapbox.setOptions(this.idLayer, 'setPaintProperty', paintOpts);
111+
this.mapbox.setOptions(this.idLayer, 'setLayoutProperty', convertedOpts.layout);
112+
this.mapbox.setOptions(this.idLayer, 'setPaintProperty', convertedOpts.paint);
108113
}
109114
};
110115

@@ -127,42 +132,63 @@ function isVisible(opts) {
127132
);
128133
}
129134

130-
function convertPaintOpts(opts) {
131-
var paintOpts = {};
135+
function convertOpts(opts) {
136+
var layout = {},
137+
paint = {};
132138

133139
switch(opts.type) {
134140

135141
case 'circle':
136-
var circle = opts.circle;
137-
Lib.extendFlat(paintOpts, {
138-
'circle-radius': circle.radius,
139-
'circle-color': circle.color,
142+
Lib.extendFlat(paint, {
143+
'circle-radius': opts.circle.radius,
144+
'circle-color': opts.color,
140145
'circle-opacity': opts.opacity
141146
});
142147
break;
143148

144149
case 'line':
145-
var line = opts.line;
146-
Lib.extendFlat(paintOpts, {
147-
'line-width': line.width,
148-
'line-color': line.color,
150+
Lib.extendFlat(paint, {
151+
'line-width': opts.line.width,
152+
'line-color': opts.color,
149153
'line-opacity': opts.opacity
150154
});
151155
break;
152156

153157
case 'fill':
154-
var fill = opts.fill;
155-
Lib.extendFlat(paintOpts, {
156-
'fill-color': fill.color,
157-
'fill-outline-color': fill.outlinecolor,
158+
Lib.extendFlat(paint, {
159+
'fill-color': opts.color,
160+
'fill-outline-color': opts.fill.outlinecolor,
158161
'fill-opacity': opts.opacity
159162

160163
// no way to pass specify outline width at the moment
161164
});
162165
break;
166+
167+
case 'symbol':
168+
var symbol = opts.symbol,
169+
textOpts = convertTextOpts(symbol.textposition, symbol.iconsize);
170+
171+
Lib.extendFlat(layout, {
172+
'icon-image': symbol.icon + '-15',
173+
'icon-size': symbol.iconsize / 10,
174+
175+
'text-field': symbol.text,
176+
'text-size': symbol.textfont.size,
177+
'text-anchor': textOpts.anchor,
178+
'text-offset': textOpts.offset
179+
180+
// TODO font family
181+
//'text-font': symbol.textfont.family.split(', '),
182+
});
183+
184+
Lib.extendFlat(paint, {
185+
'text-color': symbol.textfont.color,
186+
'text-opacity': opts.opacity
187+
});
188+
break;
163189
}
164190

165-
return paintOpts;
191+
return { layout: layout, paint: paint };
166192
}
167193

168194
function convertSourceOpts(opts) {

src/plots/mapbox/layout_attributes.js

+41-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99

1010
'use strict';
1111

12+
var Lib = require('../../lib');
1213
var defaultLine = require('../../components/color').defaultLine;
14+
var fontAttrs = require('../font_attributes');
15+
var textposition = require('../../traces/scatter/attributes').textposition;
1316

1417

1518
module.exports = {
@@ -125,7 +128,7 @@ module.exports = {
125128

126129
type: {
127130
valType: 'enumerated',
128-
values: ['circle', 'line', 'fill'],
131+
values: ['circle', 'line', 'fill', 'symbol'],
129132
dflt: 'line',
130133
role: 'info',
131134
description: [
@@ -206,6 +209,43 @@ module.exports = {
206209
}
207210
},
208211

212+
symbol: {
213+
icon: {
214+
valType: 'string',
215+
dflt: 'circle',
216+
role: 'style',
217+
description: [
218+
'Sets the symbol icon image.',
219+
'Full list: https://www.mapbox.com/maki-icons/'
220+
].join(' ')
221+
},
222+
iconsize: {
223+
valType: 'number',
224+
dflt: 10,
225+
role: 'style',
226+
description: [
227+
'Sets the icon size.',
228+
'Has an effect only when `type` is set to *symbol*.'
229+
].join(' ')
230+
},
231+
text: {
232+
valType: 'string',
233+
dflt: '',
234+
role: 'info',
235+
description: [
236+
'Sets the symbol text.'
237+
].join(' ')
238+
},
239+
textfont: Lib.extendDeep({}, fontAttrs, {
240+
description: [
241+
'Sets the icon text font.',
242+
'Has an effect only when `type` is set to *symbol*.'
243+
].join(' '),
244+
family: {
245+
dflt: 'Open Sans Regular, Arial Unicode MS Regular'
246+
}
247+
}),
248+
textposition: Lib.extendFlat({}, textposition, { arrayOk: false })
209249
}
210250
}
211251

src/plots/mapbox/layout_defaults.js

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ function handleLayerDefaults(containerIn, containerOut) {
7676
coerce('fill.outlinecolor');
7777
}
7878

79+
if(type === 'symbol') {
80+
coerce('symbol.icon');
81+
coerce('symbol.iconsize');
82+
83+
coerce('symbol.text');
84+
Lib.coerceFont(coerce, 'symbol.textfont');
85+
coerce('symbol.textposition');
86+
}
7987

8088
layersOut.push(layerOut);
8189
}

src/traces/scattermapbox/attributes.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
var scatterGeoAttrs = require('../scattergeo/attributes');
1212
var scatterAttrs = require('../scatter/attributes');
13+
var mapboxAttrs = require('../../plots/mapbox/layout_attributes');
1314
var plotAttrs = require('../../plots/attributes');
1415
var extendFlat = require('../../lib/extend').extendFlat;
1516

@@ -104,8 +105,8 @@ module.exports = {
104105
},
105106
fillcolor: scatterAttrs.fillcolor,
106107

107-
textfont: extendFlat({}, scatterAttrs.textfont, { arrayOk: false }),
108-
textposition: extendFlat({}, scatterAttrs.textposition, { arrayOk: false }),
108+
textfont: mapboxAttrs.layers.symbol.textfont,
109+
textposition: mapboxAttrs.layers.symbol.textposition,
109110

110111
hoverinfo: extendFlat({}, plotAttrs.hoverinfo, {
111112
flags: ['lon', 'lat', 'text', 'name']

test/jasmine/tests/mapbox_test.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ describe('mapbox defaults', function() {
107107
type: 'circle',
108108
color: 'green'
109109
}),
110+
Lib.extendFlat({}, base, {
111+
type: 'symbol',
112+
color: 'yellow'
113+
})
114+
]
110115
}
111116
};
112117

@@ -116,16 +121,25 @@ describe('mapbox defaults', function() {
116121
expect(layoutOut.mapbox.layers[0].line.width).toEqual(3);
117122
expect(layoutOut.mapbox.layers[0].fill).toBeUndefined();
118123
expect(layoutOut.mapbox.layers[0].circle).toBeUndefined();
124+
expect(layoutOut.mapbox.layers[0].symbol).toBeUndefined();
119125

120126
expect(layoutOut.mapbox.layers[1].color).toEqual('blue');
121127
expect(layoutOut.mapbox.layers[1].fill.outlinecolor).toEqual('#d3d3d3');
122128
expect(layoutOut.mapbox.layers[1].line).toBeUndefined();
123129
expect(layoutOut.mapbox.layers[1].circle).toBeUndefined();
130+
expect(layoutOut.mapbox.layers[1].symbol).toBeUndefined();
124131

125132
expect(layoutOut.mapbox.layers[2].color).toEqual('green');
126133
expect(layoutOut.mapbox.layers[2].circle.radius).toEqual(20);
127134
expect(layoutOut.mapbox.layers[2].line).toBeUndefined();
128135
expect(layoutOut.mapbox.layers[2].fill).toBeUndefined();
136+
expect(layoutOut.mapbox.layers[2].symbol).toBeUndefined();
137+
138+
expect(layoutOut.mapbox.layers[3].color).toEqual('yellow');
139+
expect(layoutOut.mapbox.layers[3].symbol.icon).toEqual('monument');
140+
expect(layoutOut.mapbox.layers[3].line).toBeUndefined();
141+
expect(layoutOut.mapbox.layers[3].fill).toBeUndefined();
142+
expect(layoutOut.mapbox.layers[3].circle).toBeUndefined();
129143
});
130144
});
131145

@@ -363,14 +377,14 @@ describe('mapbox plots', function() {
363377
};
364378

365379
var styleUpdate0 = {
366-
'mapbox.layers[0].fill.color': 'red',
380+
'mapbox.layers[0].color': 'red',
367381
'mapbox.layers[0].fill.outlinecolor': 'blue',
368382
'mapbox.layers[0].opacity': 0.3
369383
};
370384

371385
var styleUpdate1 = {
386+
'mapbox.layers[1].color': 'blue',
372387
'mapbox.layers[1].line.width': 3,
373-
'mapbox.layers[1].line.color': 'blue',
374388
'mapbox.layers[1].opacity': 0.6
375389
};
376390

0 commit comments

Comments
 (0)