最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Making a Backbone.js view to draw objects on a canvas - Stack Overflow

programmeradmin1浏览0评论

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.

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.

Share Improve this question asked May 23, 2012 at 8:45 rpabonrpabon 1,2012 gold badges17 silver badges22 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 18

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.

Also you may try to use Backbone.KineticView plugin to add canvas support to Backbone. It works via KineticJS, so may also use all power of event delegation for canvas nodes.

Example:

var MyView = Backbone.KineticView.extend({
  // build Kineticjs object, then return it.
  el : function(){
    var rect = new Kinetic.Rect({
      x : 100,
      y : 100,
      width : 50,
      height : 50,
      fill : 'green',
      id : 'rect'
    });
    var circle = new Kinetic.Circle({
      x : 200,
      y : 100,
      radius : 50,
      fill : 'red',
      name : 'circle'
    });
    var group = new Kinetic.Group();
    group.add(rect).add(circle);
    return group;
  },
  // setup events
  events : {
    'click #rect' : function(){
      console.log("on rectangle clicked");
    },
    'mouseover .circle' : 'onMouseOverCircle'
  },
  onMouseOverCircle : function(){
    console.log('Mouse is over circle');
  },
  render : function(){
    // this.$el - cached kineticjs object.
    this.options.layer.add(this.$el);
    layer.draw();
  }
});

var stage = new Kinetic.Stage({
  container : 'container',
  width : 300,
  height : 300
});
var layer = new Kinetic.Layer();
stage.add(layer);

view = new MyView({layer:layer});
view.render();
发布评论

评论列表(0)

  1. 暂无评论