Frame-rate limiter for m.mount/m.route
This commit is contained in:
parent
5ec06e7c08
commit
db609b9142
5 changed files with 147 additions and 13 deletions
35
limiter.js
Normal file
35
limiter.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
var FRAME_BUDGET = 16 // 60 frames per second = 1 call per 16 ms
|
||||
|
||||
module.exports = function($window, render) {
|
||||
var rAF = $window.requestAnimationFrame || $window.setTimeout
|
||||
var cAF = $window.cancelAnimationFrame || $window.clearTimeout
|
||||
|
||||
var last = 0
|
||||
var pending
|
||||
|
||||
return function() {
|
||||
var now = new Date()
|
||||
|
||||
// First render, OR if the time since the last render is greater
|
||||
// than the frame budget
|
||||
// just immediately render
|
||||
if(!last || now - last > FRAME_BUDGET) {
|
||||
last = now;
|
||||
|
||||
return render()
|
||||
}
|
||||
|
||||
// Redraw already pending, abort
|
||||
if(pending) {
|
||||
return
|
||||
}
|
||||
|
||||
// Schedule a redraw for the next tick
|
||||
pending = rAF(function() {
|
||||
render()
|
||||
|
||||
last = new Date()
|
||||
pending = null
|
||||
}, FRAME_BUDGET - (now - last))
|
||||
}
|
||||
}
|
||||
51
mithril.js
51
mithril.js
|
|
@ -575,21 +575,58 @@ var createRenderer = function($window) {
|
|||
return {render: render, setEventCallback: setEventCallback}
|
||||
}
|
||||
|
||||
var FRAME_BUDGET = 16 // 60 frames per second = 1 call per 16 ms
|
||||
|
||||
var limiter = function($window, render) {
|
||||
var rAF = $window.requestAnimationFrame || $window.setTimeout
|
||||
var cAF = $window.cancelAnimationFrame || $window.clearTimeout
|
||||
|
||||
var last = 0
|
||||
var pending
|
||||
|
||||
return function() {
|
||||
var now = new Date()
|
||||
|
||||
// First render, OR if the time since the last render is greater
|
||||
// than the frame budget
|
||||
// just immediately render
|
||||
if(!last || now - last > FRAME_BUDGET) {
|
||||
last = now;
|
||||
|
||||
return render()
|
||||
}
|
||||
|
||||
// Redraw already pending, abort
|
||||
if(pending) {
|
||||
return
|
||||
}
|
||||
|
||||
// Schedule a redraw for the next tick
|
||||
pending = rAF(function() {
|
||||
render()
|
||||
|
||||
last = new Date()
|
||||
pending = null
|
||||
}, FRAME_BUDGET - (now - last))
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
var createMounter = function($window, redraw) {
|
||||
return function(root, component) {
|
||||
var renderer = createRenderer($window)
|
||||
renderer.setEventCallback(draw)
|
||||
|
||||
function draw() {
|
||||
var draw = limiter($window, function draw() {
|
||||
renderer.render(root, {tag: component})
|
||||
}
|
||||
})
|
||||
|
||||
renderer.setEventCallback(draw)
|
||||
|
||||
redraw.run = draw
|
||||
draw()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var buildQueryString = function buildQueryString(object) {
|
||||
if (Object.prototype.toString.call(object) !== "[object Object]") return ""
|
||||
|
||||
|
|
@ -758,15 +795,17 @@ var createRouter = function($window) {
|
|||
return {setPrefix: setPrefix, getPath: getPath, setPath: setPath, defineRoutes: defineRoutes, link: link}
|
||||
}
|
||||
|
||||
|
||||
var createRouterInstance = function($window, redraw) {
|
||||
var renderer = createRenderer($window)
|
||||
var router = createRouter($window)
|
||||
var route = function(root, defaultRoute, routes) {
|
||||
var replay = router.defineRoutes(routes, function(component, args) {
|
||||
var replay = limiter($window, router.defineRoutes(routes, function(component, args) {
|
||||
renderer.render(root, {tag: component, attrs: args})
|
||||
}, function() {
|
||||
router.setPath(defaultRoute)
|
||||
})
|
||||
}))
|
||||
|
||||
renderer.setEventCallback(replay)
|
||||
redraw.run = replay
|
||||
}
|
||||
|
|
|
|||
11
mount.js
11
mount.js
|
|
@ -1,15 +1,16 @@
|
|||
var createRenderer = require("./render/render")
|
||||
var limiter = require("./limiter");
|
||||
|
||||
module.exports = function($window, redraw) {
|
||||
return function(root, component) {
|
||||
var renderer = createRenderer($window)
|
||||
renderer.setEventCallback(draw)
|
||||
|
||||
function draw() {
|
||||
var draw = limiter($window, function draw() {
|
||||
renderer.render(root, {tag: component})
|
||||
}
|
||||
})
|
||||
|
||||
renderer.setEventCallback(draw)
|
||||
|
||||
redraw.run = draw
|
||||
draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
var createRenderer = require("./render/render")
|
||||
var createRouter = require("./router/router")
|
||||
var limiter = require("./limiter")
|
||||
|
||||
module.exports = function($window, redraw) {
|
||||
var renderer = createRenderer($window)
|
||||
var router = createRouter($window)
|
||||
var route = function(root, defaultRoute, routes) {
|
||||
var replay = router.defineRoutes(routes, function(component, args) {
|
||||
var replay = limiter($window, router.defineRoutes(routes, function(component, args) {
|
||||
renderer.render(root, {tag: component, attrs: args})
|
||||
}, function() {
|
||||
router.setPath(defaultRoute)
|
||||
})
|
||||
}))
|
||||
|
||||
renderer.setEventCallback(replay)
|
||||
redraw.run = replay
|
||||
}
|
||||
|
|
|
|||
57
test-redraw.html
Normal file
57
test-redraw.html
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head></head>
|
||||
<style>
|
||||
html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.mount {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.outer {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.inner {
|
||||
height: 99999px;
|
||||
background: #CCC;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="mount"></div>
|
||||
<script src="./module/module.js"></script>
|
||||
<script src="./mithril.js"></script>
|
||||
<script type="text/javascript">
|
||||
var m = require("./mithril")
|
||||
|
||||
var last = 0
|
||||
|
||||
m.mount(document.querySelector(".mount"), {
|
||||
view : function() {
|
||||
var now = performance.now()
|
||||
console.log("draw", now - last)
|
||||
last = now
|
||||
|
||||
return m(".outer", {
|
||||
onscroll : function() {
|
||||
// Unused except to trigger redraws
|
||||
}
|
||||
},
|
||||
m(".inner",
|
||||
m("p", "Scroll me")
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue