Skip to content

Instantly share code, notes, and snippets.

@linrock
Last active December 11, 2015 22:28
Show Gist options
  • Save linrock/4669969 to your computer and use it in GitHub Desktop.
Save linrock/4669969 to your computer and use it in GitHub Desktop.
Demo
<!DOCTYPE html>
<html>
<head>
<style>
body {
overflow: hidden;
font-family: Arial, sans-serif;
background: #222;
color: #eee;
margin: 0;
padding: 0;
}
button {
display: none;
border: 0;
border-radius: 3px;
background: gray;
font-size: 16px;
color: white;
padding: 0px 8px;
margin-right: 10px;
line-height: 28px;
}
button:hover {
cursor: pointer;
}
.light {
background: #ddd;
}
.dark {
color: #222;
}
.circle {
border-radius: 9999px;
background: black;
width: 10px;
height: 10px;
top: -999px;
left: -999px;
position: absolute;
}
#controls {
z-index: 5;
position: absolute;
font-size: 28px;
font-weight: bold;
padding: 20px;
}
#overlay {
display: none;
width: 100%;
height: 100%;
position: absolute;
color: white;
font-size: 30px;
text-align: center;
padding-top: 100px;
z-index: 4;
background: black;
}
#world {
width: 100%;
height: 100%;
position: absolute;
z-index: 3;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.3/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js"></script>
<script src="https://gist.github.com/raw/1579671/7f515ade253afbc860dac1f84e21998d54359d79/rAF.js"></script>
<script>
const FPS = 50;
var w = window.innerWidth;
var h = window.innerHeight;
window.dispatcher = _.clone(Backbone.Events);
function rand(a,b) {
return ~~(Math.random()*(b-a))+a;
}
var ControlsView = Backbone.View.extend({
el: "#controls",
events: {
"click #disperse" : "disperse",
},
counter: 0,
initialize: function() {
this.$pause = this.$("#pause");
this.$disperse = this.$("#disperse");
this.$counter = this.$("#counter");
this.listenTo(dispatcher, "world:spawn", this.incrementCounter);
this.listenTo(dispatcher, "world:invert", this.invertColor);
this.$counter.text(0);
},
incrementCounter: function() {
this.counter += 1;
this.$counter.text(this.counter);
},
invertColor: function() {
this.$el.toggleClass("dark");
},
disperse: function() {
dispatcher.trigger("world:disperse");
},
});
var OverlayView = Backbone.View.extend({
el: "#overlay",
initialize: function() {
this.listenTo(dispatcher, "world:pause", this.pause);
this.listenTo(dispatcher, "world:unpause", this.unpause);
this.listenTo(dispatcher, "world:disperse", this.flash);
},
pause: function() {
this.$el.show().text("PAUSED").css({ opacity: 1, background: "rgba(0,0,0,0.5)" });
},
unpause: function() {
this.$el.hide().empty();
},
flash: function() {
this.$el.show()
.css({ background: "yellow", opacity: 0.5 })
.animate({ opacity: 0 }, 150, function() { $(this).hide(); });
}
});
var WorldView = Backbone.View.extend({
el: "#world",
events: {
"click" : "invertEverything"
},
initialize: function() {
this.listenTo(dispatcher, "world:invert", this.invertBackground);
this.listenTo(dispatcher, "world:spawn", this.spawnCircle);
_(15).times(this.spawnCircle, this);
},
spawnCircle: function() {
var circleView = new CircleView;
this.$el.append(circleView.render());
},
invertEverything: function() {
dispatcher.trigger("world:invert");
},
invertBackground: function() {
this.$el.toggleClass("light");
}
});
var CircleView = Backbone.View.extend({
className: "circle",
events: {
"mouseenter" : "disperse"
},
paused: false,
render: function() {
var colors = ["#ddffcc", "#c3f0f2", "#b3ecef", "#9ae4e8", "#30d8f0"];
var colors = ["#55476a", "#a13d63", "#db3853", "#f45c44", "#f8b646"];
this.$el.css({
background: colors[rand(0,5)],
x: this.x,
y: this.y,
width: this.size,
height: this.size
});
return this.$el;
},
initialize: function() {
this.size = rand(10,60);
this.wmax = w - this.size;
this.hmax = h - this.size;
this.x = rand(0,w-this.size);
this.y = rand(0,h-this.size);
this.opacity = 0;
this.vx = rand(1,3);
this.vy = rand(1,3);
this.dop = 0.005*rand(1,5);
this.listenTo(dispatcher, "world:animate", this.animate);
this.listenTo(dispatcher, "world:pause", this.pause);
this.listenTo(dispatcher, "world:unpause", this.unpause);
this.listenTo(dispatcher, "world:invert", this.invert);
this.listenTo(dispatcher, "world:disperse", this.disperse);
},
animate: function() {
if (this.paused) {
return;
}
this.x += this.vx;
this.y += this.vy;
if (this.x < 0 || this.x > this.wmax) {
this.vx *= -1;
}
if (this.y < 0 || this.y > this.hmax) {
this.vy *= -1;
}
this.fade();
this.$el.css({
top: this.y,
left: this.x,
opacity: this.opacity
});
},
fade: function() {
this.opacity += this.dop;
if (this.opacity > 1) {
this.opacity = 1;
this.dop *= -1;
}
if (this.opacity < 0) {
this.remove();
dispatcher.trigger("world:spawn");
}
},
pause: function() {
this.paused = true;
},
unpause: function() {
this.paused = false;
},
invert: function() {
this.vx *= -1;
this.vy *= -1;
},
disperse: function() {
this.vx = rand(2,7) * (Math.random() < 0.5 ? 1 : -1);
this.vy = rand(2,7) * (Math.random() < 0.5 ? 1 : -1);
}
});
$(function() {
new ControlsView;
new OverlayView;
new WorldView;
// setInterval(function() { dispatcher.trigger("animate"); }, 1000/FPS);
(function step() { dispatcher.trigger("world:animate"); requestAnimationFrame(step); })();
});
</script>
</head>
<body>
<div id="controls">
<button id="disperse">Disperse</button>
<span id="counter"></span>
</div>
<div id="overlay"></div>
<div id="world"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment