Skip to content
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

Fix animation performance #8913

Merged
merged 3 commits into from
Nov 13, 2019
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
64 changes: 50 additions & 14 deletions debug/animate.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link rel='stylesheet' href='../dist/mapbox-gl.css' />
<style>
#map { width: 764px; height: 400px; }
#map { width: 1200px; height: 800px; }
</style>
</head>

Expand All @@ -21,42 +21,78 @@
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [0, 0],
zoom: 2
zoom: 4
});

var radius = 20;
var radius = 30;

function pointOnCircle(angle) {
function line(angle, radius) {
return {
"type": "Point",
"coordinates": [
Math.cos(angle) * radius,
Math.sin(angle) * radius
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[-Math.cos(angle) * radius, -Math.sin(angle) * radius + 1],
[Math.cos(angle) * radius, Math.sin(angle) * radius + 1],
]
}
};
}

function crossWithAngle(angle) {
return {
"type": "FeatureCollection",
"features": [
line(angle - Math.PI / 4, radius),
line(angle + Math.PI / 4, radius)
]
};
}

map.on('load', function () {
// Add a source and layer displaying a point which will be animated in a circle.
map.addSource('point', {
map.addSource('lines', {
"type": "geojson",
"data": pointOnCircle(0)
"data": crossWithAngle(0)
});

map.addLayer({
"id": "point",
"source": "point",
"id": "lines",
"source": "lines",
"type": "line",
"paint": {
"line-width": 4,
"line-color": "#007cbf"
}
});

map.addLayer({
"id": "dot",
"source": "lines",
"type": "circle",
"paint": {
"circle-radius": 10,
"circle-color": "#007cbf"
}
});

var updates = 0;

map.on('data', function (d) {
if (d.sourceDataType === 'content') {
updates++;
}
});

setInterval(function () {
console.log(updates + ' updates per second');
updates = 0;
}, 1000);

function animateMarker(timestamp) {
// Update the data to a new position based on the animation timestamp. The
// divisor in the expression `timestamp / 1000` controls the animation speed.
map.getSource('point').setData(pointOnCircle(timestamp / 1000));
map.getSource('lines').setData(crossWithAngle(timestamp / 1000));

// Request the next frame of the animation.
requestAnimationFrame(animateMarker);
Expand All @@ -68,4 +104,4 @@
</script>

</body>
</html>
</html>
12 changes: 9 additions & 3 deletions src/util/actor.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow

import {bindAll} from './util';
import {bindAll, isWorker} from './util';
import {serialize, deserialize} from './web_worker_transfer';
import ThrottledInvoker from './throttled_invoker';

Expand Down Expand Up @@ -107,15 +107,21 @@ class Actor {
cancel();
}
} else {
// Store the tasks that we need to process before actually processing them. This
// In workers, store the tasks that we need to process before actually processing them. This
// is necessary because we want to keep receiving messages, and in particular,
// <cancel> messages. Some tasks may take a while in the worker thread, so before
// executing the next task in our queue, postMessage preempts this and <cancel>
// messages can be processed. We're using a MessageChannel object to get throttle the
// process() flow to one at a time.
this.tasks[id] = data;
this.taskQueue.push(id);
this.invoker.trigger();
if (isWorker()) {
this.invoker.trigger();
} else {
// In the main thread, process messages immediately so that other work does not slip in
// between getting partial data back from workers.
this.process();
}
}
}

Expand Down