Jank-free rendering on canvas
A failed attempt at jank-free rendering on HTML5 canvas.
HTML
<body>
<canvas id="screen" width="800" height="600"></canvas>
</body>
CSS
canvas {
width: 800px;
height: 600px;
}
JavaScript
// A simple utility for executing multiple tasks within one requestAnimationCallback.
// Priority tasks are executed before idle tasks. The utility makes it easier to
// split long-running rendering tasks into batches whose duration does not exceed
// the deadline provided in the parameter.
var RequestAnimationFrameManager = function(deadlineMs) {
var priority = [];
var idle = [];
var animationFrameRequested = false;
this.schedulePriorityTask = function (task) {
priority.push(task);
schedule();
};
this.scheduleIdleTask = function (task) {
idle.push(task);
schedule();
};
function schedule() {
if (!animationFrameRequested) {
requestAnimationFrame(processQueues);
animationFrameRequested = true;
}
}
function processQueues(now) {
animationFrameRequested = false;
var i, task;
var started = window.performance.now();
var deadline = started + deadlineMs;
var priorityTasksToRun = priority;
var idleTasksToRun = idle;
priority = [];
idle = [];
execute(priorityTasksToRun, priority);
execute(idleTasksToRun, idle);
if (priority.length > 0 || idle.length > 0) {
schedule();
}
function execute(tasks, nextTasks) {
for (i = 0; i < tasks.length; i++) {
task = tasks[i];
var taskStart = window.performance.now();
if (taskStart < deadline) {
// Let the task know what the current deadline is.
// It is the responsibility of the task to return
// before the deadline passes.
var completed = task(now, taskStart, deadline);
if (completed) {
continue;
}
}
nextTasks.push(task);
}
}
}
};
// Allow 12ms for each frame.
var rafManager = new RequestAnimationFrameManager(12);
// Set up canvas
var screenCanvas = document.getElementById("screen");
var width = screenCanvas.width, height = screenCanvas.height;
// Initialize drawing context
var screenCtx...