Making a Backbone.js view to draw objects on a canvas

backbone.js, canvas, html, javascript

Solution

I would follow the separation of models and views offered by Backbone. Keep your models as data repositories :

var Box = Backbone.Model.extend({
    defaults: {
        x: 0,
        y: 0,
        w: 1,
        h: 1,
        color: "#FF9000",
        linewidth: 3
        // don't define a default id, that leads to strange behaviors
    }
});

var BoxSet = Backbone.Collection.extend({
    model:Box
});

And define the views to render the different pieces on a canvas:

var BoxView = Backbone.View.extend({
    render: function() {
        var model = this.model, ctx = this.options.ctx;

        ctx.fillStyle = "#FF9000";
        ctx.globalAlpha = 0.1;
        ctx.fillRect(
            model.get("x"), model.get("y"),
            model.get("w"), model.get("h")
        ); 

        ctx.globalAlpha = 1;
        ctx.strokeStyle = model.get("color");
        ctx.lineWidth = model.get("linewidth");
        ctx.strokeRect(
            model.get("x"), model.get("y"), 
            model.get("w"), model.get("h")
        );
    }
});

var SetView= Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.collection, "all", this.render);
    },

    render: function() {
        var canvas = this.el, ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        this.collection.each(function(model) {
            var view = new BoxView({ctx: ctx, model: model});
            view.render();
        })
    }
});

And finally instantiate and render:

var c = new BoxSet();
c.add({x: 150, y: 150, w: 100, h: 100});
c.add({x: 10, y: 10, w: 100, h: 100});

var v = new SetView({
    el: $("canvas"),
    collection : c
});
v.render();

A Fiddle to view those two nice squares http://jsfiddle.net/JB9yg/

Another one where a change to the collection leads to re-rendering http://jsfiddle.net/JB9yg/1/

This example can probably be built upon to provide cleaner manipulations, but that should get you started.

Problem

I am making an application where different rectangles are painted on a canvas and I am trying to do it with Backbone. I have a model called box: ``` Box = Backbone.Model.extend({ defaults: { x: 0, y: 0, w: 1, h: 1, color: "#FF9000", linewidth: 3, id: 0, }, drawBox: function(ctx) { ctx.fillStyle = "#FF9000"; ctx.globalAlpha = 0.1; ctx.fillRect(this.get("x"), this.get("y"), this.get("w"), this.get("h")); //transparent box in the back ctx.globalAlpha = 1; ctx.strokeStyle = this.get("color"); ctx.lineWidth = this.get("linewidth"); ctx.strokeRect(this.get("x"), this.get("y"), this.get("w"), this.get("h")); //rectangle on top } }); ``` And I also have a collection of this Box model: ``` BoxSet = Backbone.Collection.extend({ model: Box }); ``` What I have in mind is to have a view where I can put every Box model in the BoxSet collection on a canvas using the drawBox method in the Box model, but so far all the tutorials and examples deal with simple text templates and I cannot figure out how to acomplish this. Any ideas on how could this be done using Backbone views? Thanks in advance.

Original source