使 JointJs & Backbone/Marionette 与 collections 一起工作(HTML 项在里面)

Making JointJs & Backbone/Marionette work with collections (HTML items inside)

如果你能以某种方式帮助我,请告诉我,我有点难以理解。

从一些 Marionette 应用程序逻辑开始:

app.js

//basic setup
this.Graph = new joint.dia.Graph;
this.Paper = new joint.dia.Paper({ width: 640, height: 480, model: this.Graph });

// [...] lots of code

//adding elements
app.Elements.add(element);

到目前为止一切顺利。现在是棘手的部分。我想要一个 collection.

JointCollectionView.js

module.exports = Marionette.CollectionView.extend({
    tagName: 'div',
    className: 'row',
    childView: JointView,

    addChild: function(child, ChildView, index){
        //does that make sense?
        app.Graph.addCell(child);

        //should i add it to collection?
        if (child.shouldBeShown()) {
            return Marionette.CollectionView.prototype.addChild.call(this,   child, ChildView, index);
        }
    },

    getChildView: function(item) {
        return app.Graph.getCell(item);
    }

    //[...]
})

现在更棘手了。我如何处理 joint-view 以使其与 collection 一起使用并显示 html 元素?

JointView.js

module.exports = joint.dia.ElementView.extend({ /* ?!?!?! */ });

//OR ?

module.exports = Marionette.ItemView.extend({
    jointElementView: null, //this will be like above somewhere else...

    initialize: function(options){
        jointElementView = new JointElementView({ /* ... */ });
    }
})

我不是 JointJS 专家,但您的实现看起来很完美。

您想使用第二个选项:

JointView.js

module.exports = Marionette.ItemView.extend({
  template: _.template("");
  jointElementView: null, //this will be like above somewhere else...

  initialize: function(options){
      this.jointElementView = new JointElementView({ /* ... */ });
  }
});

因为 Marionette.CollectionView 需要 Marionette 视图(sp. Marionette.ItemView 或后代 [LayoutView/CompositeView])。

我要添加到 JointView.js 的方法是将 this.jointElementView 的结果注入 JointView.js html。所以,给它添加一个 属性,比如:

onRender: function () {
  this.$el.append(this.jointElementView.el); // Where this.jointElementView.el is the JointJS view html
}

在@seebiscuit 的帮助下,我更深入地研究了 jointjs 并缩小了我应该如何处理这个问题的范围(不过你似乎对这些要点不感兴趣,所以我会自己回答)

编辑了以下文件:

app.js(已更改,重要!)

//this step is necessary to create these element before the paper is created.
//Make jointjs GLOBAL!!!!!!
joint.shapes.html = {};
joint.shapes.html.Element = require('views/Element');  //this dude im gonna use to create the elements 
joint.shapes.html.ElementView = require('views/ElementView');  //this badboy will fire when i create those elements. MAGIC!

//basic setup
this.Graph = new joint.dia.Graph;
this.Paper = new joint.dia.Paper({ width: 640, height: 480, model:     this.Graph });

// [...] lots of code

//adding elements
app.Elements.add(element);

JointCollectionView.js (beauti-/simplyfied)

module.exports = Marionette.CollectionView.extend({
    tagName: 'div',
    className: 'row',
    childView: JointView,

    onRender: function(){
      // jointjs' paper is added here long after jointjs custom element init.
      this.el.appendChild(app.Paper.el);
    },

    onDestroy: function(){
      // removal of the paper is done here
      this.el.removeChild(app.Paper.el);
    },

    buildChildView: function(child, JointView, childViewOptions){
      // add model, jointjs' paper and graph into JointView's options
      var options = _.extend({model: child}, childViewOptions);
          options = _.extend({paper: app.Paper, graph: app.Graph}, options);

      return new JointView(options);
    }    

    //[...]
})

JointView.js(魔法来了!)

module.exports = Marionette.ItemView.extend({
    tagName: 'div',
    className: 'html-element',
    template: "#agentTmpl",

    // store here just in case
    cell: null,

    // [...]

    initialize: function() {
      // initialize joinjs element-shape here
      Marionette.bindEntityEvents(this, this.model, this.modelEvents);

      if(this.cell == null){
        //notice `el: this.el` This will actually pass the option el to ElementView. Surprised? 
        //Yeah me too. From there i can do with the dom-element whatever i want
        this.cell = new joint.shapes.html.Element({ el: this.el, position: { x: 80, y: 80 }, size: { width: 250 } });
      }
    },

    onRender: function(){
          // after rendering add cell to graph
          this.options.graph.addCell(this.cell);
    },

    onDestroy: function(){
          // after removal remove cell from graph
          this.cell.remove();
    }
});

Element.js ElementView.js

为简单起见,或多或少像这里:http://www.jointjs.com/tutorial/html-elements 总结实际发生的事情是:每当创建一个新元素时,ElementView 将触发所有必要的事件(初始化、渲染等)。从那里您可以操纵绘制的 svg 元素或与我之前创建的 JointView html 重叠(类似于教程)。我基本上把我的 JointView dom-element 放在由 jointjs 绘制的 SVG 上。

给你。 已修复!