Skip to content

Commit

Permalink
Use styleDiff to apply setStyle changes incrementally
Browse files Browse the repository at this point in the history
Previously, calls to map.setStyle() created a new Style instance.
Creating a new Style instance is an expensive operation that abandons the
current layers and sources. For simple updates, this is very wasteful.

Instead of creating a Style object for every call of map.setStyle() we
now diff the new style with the current style and apply the delta within
a batch update.

Situations where the non-incremental setStyle is used:
- initial style for a map
- the new stylesheet is already a Style instance
- the current style is not done loading
- the style diff cannot be applied incrementally

Issue: #1341
  • Loading branch information
scothis committed Jun 29, 2015
1 parent 06efa05 commit 1a5a95c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
23 changes: 23 additions & 0 deletions js/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var DOM = require('../util/dom');

var Style = require('../style/style');
var AnimationLoop = require('../style/animation_loop');
var styleDiff = require('../style/style_diff');
var Painter = require('../render/painter');

var Transform = require('../geo/transform');
Expand Down Expand Up @@ -312,6 +313,28 @@ util.extend(Map.prototype, /** @lends Map.prototype */{
* @returns {Map} `this`
*/
setStyle: function(style) {
if (!this.style || style instanceof Style || !this.style._loaded) {
return this._setStyle(style);
}

try {
var operations = styleDiff.diff(this.style.json(), style);
if (operations.length) {
styleDiff.patch(this.style, operations);

// not worth being smart about calling _cascade and update
this.style._cascade(this._classes);
this.update(true);
}
} catch (e) {
// not all operations are supported, fall back to full _setStyle
this._setStyle(style);
}

return this;
},

_setStyle: function(style) {
if (this.style) {
this.style
.off('load', this._onStyleLoad)
Expand Down
55 changes: 55 additions & 0 deletions test/js/ui/map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,65 @@ test('Map', function(t) {
var map = createMap();

map.setStyle({version: 7, sources: {}, layers: []});
var style = map.style;
map.setStyle({version: 7, sources: {}, layers: []});

t.notOk(map.style === style, 'style is replaced');

t.end();
});

t.test('styles are updated', function(t) {
var map = createMap();

map.on('style.load', onLoad);
map.setStyle({version: 7, sources: {}, layers: []});

function onLoad() {
map.off('style.load', onLoad);

var style = map.style;
map.setStyle({version: 7, sources: {}, layers: []});
t.ok(map.style === style, 'style is updated');

t.end();
}
});

t.test('falls back to new style for incompatible changes', function(t) {
var map = createMap();

map.on('style.load', onLoad);
map.setStyle({
version: 7,
sources: {},
layers: [
{ id: 'background', type: 'background' }
]
});

function onLoad() {
map.off('style.load', onLoad);

var style = map.style;
map.setStyle({
version: 7,
sources: {},
layers: [
{
id: 'background',
type: 'background',
'paint.light': {
'background-color': '#EEE'
}
}
]
});
t.notOk(map.style === style, 'style is replaced');

t.end();
}
});
});

t.test('#resize', function(t) {
Expand Down

0 comments on commit 1a5a95c

Please sign in to comment.