1. Описание задачи
Разрабатывая крупное mind map приложение, мы выбрали Backbone в качестве основной библиотеки построения приложения. При этом карта ума рисуется через canvas элемент с помощью различных примитивов. Мы выбрали библиотеку KineticJS для работы с canvas, так как она отлично поддерживает работу с событиями для объектов на холсте.
Чтобы соответствовать архитектуре Backbone все работа с canvas (точнее с экземплярами объектов KineticJS) происходила в экземплярах Backbone.View:
var Node = Backbone.View.extend({
initialize : function(params) {
this.layer = params.layer;
this.node = this.el();
this.bindEvents();
},
el : function(){
var rect = new Kinetic.Rect({
x : 100,
y : 100,
width : 50,
height : 50,
fill : 'green',
id : 'rect'
});
return rect;
},
bindEvents: function() {
this.node.on('click', function(){
console.log("on rectangle clicked");
}
// etc ...
}
});
2. Проблема
Но Backbone View спроектирован для работы с DOM элементами, и при таком подходе генерировал не нужные нам div объекты и объявлять события в декларативном стиле (http://backbonejs.org/#View-delegateEvents) тоже не получалось.
3. Решение.
Был написан плагин Backbone.KineticView, который позволял работать с объектами на canvas (через KineticJS) в таком же стиле, как и обычный Backbone.View работает с DOM.
Пример того, как теперь выглядит код:
var MyView = Backbone.KineticView.extend({
initialize : function(params) {
this.layer = params.layer;
},
nodeType : 'Rect',
attributes : {
x : 100,
y : 100,
width : 50,
height : 50,
fill : 'green',
id : 'rect'
},
// setup events
events : {
'click' : function(){
console.log("on rectangle clicked");
}
}
render : function(){
this.layer.add(this.el);
this.layer.draw();
}
});
view = new MyView({layer:layer});
view.render();
Данный плагин почти полностью повторяет функционал Backbone.View, но только для KineticJS объектов. По аналогии были адаптированы тесты от Backbone.View.
Чуть более сложный живой пример можно посмотреть здесь: http://jsbin.com/fekex/4/edit
Код плагина: https://github.com/slash-system/backbone.kineticview
Наверно аналогичные решения можно легко построить для подобных canvas библиотек: Easeljs, FabricJS и т.д. Кто-нибудь уже решал такую задачу?