Time-Based Animation (css example)
http://viget.com/inspire/time-based-animation
by LeroyRon
HTML
<script src="http://danieltello.com/demos/time-based-animation/javascripts/requestAnimationFrame.js"></script>
<div id="css-demo">
<div class="buttons">
<label for="speed">Speed</label>
<input name="speed" id="speed-input" type="number" value="200"> px/sec</input>
<button onclick="APP.play();">Play</button>
<button onclick="APP.pause();">Pause</button>
<span class="framerate"><span id="framerate">0</span> fps</span>
</div>
<div id="css-bullet"></div>
<div id="css-cannon"></div>
</div>
CSS
body, html {
font-family: sans-serif;
font-size: 14px;
margin: 0;
padding: 0;
}
#css-demo {
background: #9adaea url(http://viget.com/uploads/file/time-based-animation/images/ground.png) repeat-x 0 100%;
}
#css-demo {
height: 338px;
max-width: 580px;
overflow: hidden;
position: relative;
width: 100%;
}
#css-bullet {
background: url(http://viget.com/uploads/file/time-based-animation/images/bullet-bill.png) no-repeat;
height: 56px;
left: 460px;
position: absolute;
top: 114px;
width: 64px;
}
#css-cannon {
background: url(http://viget.com/uploads/file/time-based-animation/images/cannon.png) no-repeat;
height: 128px;
right: 56px;
position: absolute;
top: 110px;
width: 64px;
}
#speed-input {
width: 60px;
}
.buttons {
-webkit-font-smoothing: antialiased;
background: #201400;
background: rgba(0,0,0,0.8);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
color: #fff;
font-weight: bold;
height: 50px;
line-height: 50px;
padding: 0 10px;
position: absolute;
top: 288px;
width: 100%;
z-index: 1;
}
.framerate {
float: right;
}
JavaScript
// Requires requestAnimationFrame polyfill
// https://gist.github.com/1579671
window.APP = window.APP || {};
APP.init = function() {
APP.setup.initObjects();
APP.setup.initSpeedInput();
APP.setup.addListeners();
APP.play();
};
APP.pause = function() {
window.cancelAnimationFrame(APP.animationFrameLoop);
APP.isRunning = false;
};
APP.play = function() {
if(!APP.isRunning) {
APP._then = Date.now();
APP.core.frame();
APP.isRunning = true;
}
};
APP.core = {
frame: function() {
APP.now = Date.now();
APP._delta = (APP.now - APP._then) / 1000; // Converts to seconds (optional)
APP._then = APP.now;
APP.core.update();
APP.animationFrameLoop = window.requestAnimationFrame(APP.core.frame);
},
update: function() {
APP.workers.moveObjects();
// Update css position
var wholePixelBulletX = (APP.bullet.x + 0.5) | 0; // Fast round to whole pixel
APP.bullet.element.style.left = wholePixelBulletX + 'px';
// Render Framerate every 1/4 second
if(APP.framerateDisplay.timer > 0.25) {
APP.framerateDisplay.innerHTML = (1/APP._delta) | 0; // fast round to whole number
APP.framerateDisplay.timer = 0;
} else {
APP.framerateDisplay.timer += APP._delta;
}
}
};
APP.setup = {
addListeners: function() {
// Makes demo responsive for small screens
window.addEventListener('resize', APP.workers.calculateBulletStart);
},
initSpeedInput: function() {
APP.speedInput = document.getElementById('speed-input');
APP.speedInput.value = APP.bullet.speed;
APP.speedInput.addEventListener('keyup', APP.workers.updateSpeed);
APP.speedInput.addEventListener('change', APP.workers.updateSpeed);
},
initObjects: function() {
APP.bullet = {
element: document.getElementById('css-bullet'),
x: 460,
...