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 и т.д. Кто-нибудь уже решал такую задачу?
