JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script src="http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.4.min.js"></script>

<button onclick="runBackbone()">Animate with Backbone</button>
<button onclick="runEmber()">Animate with Ember</button>

<div id="grid"></div>

<script type="x-template" id="underscore-template">
  <div class="box" id="box-<%= number %>" style="top: <%= top %>px; left: <%= left %>px; background: rgb(0,0,<%= color %>);">
    <%= content %>       
  </div>
</script>
        
<script type="text/x-handlebars" id="handlebars-template" data-template-name="box">
    <div class="box" {{bindAttr id="model.number" style="model.style"}}>
      {{ model.content }}       
    </div>
</script>

CSS

#grid {
  margin: 10px;   
}

.box-view {
  width: 20px; height: 20px;
  float: left;
  position: relative;
  margin: 8px;    
}

.box {
  border-radius: 100px;
  width: 20px; height: 10px;
  padding: 5px 0;
  color: #fff;
  font: 10px/10px Arial;
  text-align: center;
  position: absolute;
}

JavaScript

// Change N to change the number of drawn circles.

var N = 100;

// The Backbone implementation:
(function(){
    
var Box = Backbone.Model.extend({

    defaults: {
        top: 0,
        left: 0,
        color: 0,
        content: 0
    },
    
    initialize: function() {
        this.count = 0;
    },

    tick: function() {
        var count = this.count += 1;
        this.set({
            top: Math.sin(count / 10) * 10,
            left: Math.cos(count / 10) * 10,
            color: (count) % 255,
            content: count % 100
        });
    }        

});


var BoxView = Backbone.View.extend({
    
    className: 'box-view',
    
    template: _.template($('#underscore-template').html()),
   
    initialize: function() {
        this.model.bind('change', function() {
            if (!this.box) return;
            var attrs = this.model.attributes;
            this.box.css({
                top: attrs.top, 
                left: attrs.left, 
                background: 'rgb(0,0,' + attrs.color + ')'
            }).html(attrs.content);
        }, this);
    },
    
    render: function() {
        this.$el.html(this.template(this.model.attributes));
        this.box = this.$('.box');
        return this;
    }
    
});

var boxes;

var backboneInit = function() {
    boxes = _.map(_.range(N), function(i) {
        var box = new Box({number: i});
        var view = new BoxView({model: box});
        $('#grid').append(view.render().el);
        return box;
    });
};

var backboneAnimate = function() {
    for (var i = 0, l = boxes.length; i < l; i++) {
      boxes[i].tick();   
    }
    window.timeout = _.defer(backboneAnimate);
};

window.runBackbone = function() {
  reset();
  backboneInit();
  backboneAnimate();    
};

})();

// The Ember implementation:
(function(){
    
var Box = Ember.Object.extend({
    
    top: 0,
    left: 0,
    content: 0,
    count: 0,
    
    tick: function() {
        var count = this.get('count') + 1;
       ...