<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<div class="container">
<div class="row">
<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>
</div>
</div>
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%;
margin:50px 0px 0px 250px;
}
#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;
}
// 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,
y: 114,
height: 56,
width: 64,
startX: 460,
speed: 100 // pixels per second
};
APP.cannon = {
element: document.getElementById('css-cannon'),
x: 460,
y: 110,
height: 128,
width: 64
};
// Update start X based on screen size
APP.workers.calculateBulletStart();
APP.bullet.x = APP.bullet.startX;
APP.framerateDisplay = document.getElementById('framerate');
APP.framerateDisplay.timer = 0;
}
};
APP.workers = {
moveObjects: function() {
// Move bullet's x position
var velocity = APP.bullet.speed * APP._delta;
APP.bullet.x = APP.bullet.x - velocity;
// Reset when off screen
if (APP.bullet.x < - APP.bullet.width) {
APP.bullet.x = APP.bullet.startX;
}
},
calculateBulletStart: function() {
APP.bullet.startX = APP.cannon.element.offsetLeft;
},
updateSpeed: function(e) {
APP.bullet.speed = APP.speedInput.value;
}
};
APP.init();