JointJS:不同对象的多个模板

JointJS: Multiple Templates for different Objects

我实际上正在开发一种可视化数据流的工具。我有不同的类型 应该使用的元素,并且希望每个元素(对象)都有一个自己的 html 模板。有人知道这是否可行以及如何实现吗?

非常感谢您的帮助,非常感谢!

尊敬的问候,

拉斐尔

这是我的代码(抱歉弄乱了):

     (function() {

    var graph = new joint.dia.Graph;
    var paper = new joint.dia.Paper({ el: $('#paper'), width: 650, height: 400, gridSize: 1, model: graph });

// Create a system element.
// -----------------------------------------------------------------------------
    joint.shapes.html = {};
    joint.shapes.html.Element = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
        markup: '<g class="rotatable"><g class="scalable"><rect/></g><g class="inPorts"/><g class="outPorts"/></g>',
        portMarkup: '<g class="port<%= id %>"><circle/></g>',
        defaults: joint.util.deepSupplement({
            type: 'html.Element',
            size: { width: 100, height: 80 },
            inPorts: [],
            outPorts: [],
            attrs: {
                '.': { magnet: false },
                rect: {
                    stroke: 'none', 'fill-opacity': 0, width: 170, height: 250,
                },
                circle: {
                    r: 6, //circle radius
                    magnet: true,
                    stroke: 'black'
                },

                '.inPorts circle': { fill: 'green', magnet: 'passive', type: 'input'},
                '.outPorts circle': { fill: 'red', type: 'output'}
            }
        }, joint.shapes.basic.Generic.prototype.defaults),
        getPortAttrs: function (portName, index, total, selector, type) {

            var attrs = {};
            var portClass = 'port' + index;
            var portSelector = selector + '>.' + portClass;
            var portCircleSelector = portSelector + '>circle';
            attrs[portCircleSelector] = { port: { id: portName || _.uniqueId(type), type: type } };
            attrs[portSelector] = { ref: 'rect', 'ref-y': (index + 0.5) * (1 / total) };
            if (selector === '.outPorts') { attrs[portSelector]['ref-dx'] = 0; }
            return attrs;
        }
    }));
// -------------------------------------------------------------------------------------------------------------------------------------


// Create a custom view for that element that displays an HTML div above it.
// -------------------------------------------------------------------------------------------------------------------------------------


    joint.shapes.html.ElementView = joint.dia.ElementView.extend({
        objectname: "System",
        template: [
            '<div class="html-element" id=>',
            '<button class="delete">x</button>',
            '<button class="add">+</button>',
            '<div class="head">',
            '<h3>',
            'System',
            '</h3>',
            '<input type="text" class="systemComment" placeholder = "Add a comment to this System"/>',
            '</div> </br>',
            '</div>'
        ].join(''), 

        //::: Start initialize function :::
         initialize: function() {
            _.bindAll(this, 'updateBox');
            joint.dia.ElementView.prototype.initialize.apply(this, arguments);            

            this.$box = $(_.template(this.template)());
            // Prevent paper from handling pointerdown.
            this.$box.find('input,select').on('mousedown click', function(evt) {
                evt.stopPropagation();
            });
            // This is an example of reacting on the input change and storing the input data in the cell model.
            this.$box.find('input').on('change', _.bind(function(evt) {
                this.model.set('input', $(evt.target).val());
            }, this));
            this.$box.find('select').on('change', _.bind(function(evt) {
                this.model.set('select', $(evt.target).val());
            }, this));
            this.$box.find('select').val(this.model.get('select'));
            this.$box.find('.delete').on('click', _.bind(this.model.remove, this.model));
            $('.add').on('click', function(){
                //we select the box clone it and insert it after the box
                $(".html-element").clone().appendTo("#paper");
            });
            // Update the box position whenever the underlying model changes.
            this.model.on('change', this.updateBox, this);
            // Remove the box when the model gets removed from the graph.
            this.model.on('remove', this.removeBox, this);

            this.updateBox();
        },
        //::: End initialize function :::

        //::: Start render function :::
        render: function() {
            joint.dia.ElementView.prototype.render.apply(this, arguments);
            this.paper.$el.prepend(this.$box);
            // this.paper.$el.mousemove(this.onMouseMove.bind(this)), this.paper.$el.mouseup(this.onMouseUp.bind(this));
            this.updateBox();
            return this;
        },
        //::: End render function :::

        //::: Start renderPortst function :::
        renderPorts: function () {
            var $inPorts = this.$('.inPorts').empty();
            var $outPorts = this.$('.outPorts').empty();

            var portTemplate = _.template(this.model.portMarkup);

            _.each(_.filter(this.model.ports, function (p) { return p.type === 'in' }), function (port, index) {

                $inPorts.append(V(portTemplate({ id: index, port: port })).node);
            });
            _.each(_.filter(this.model.ports, function (p) { return p.type === 'out' }), function (port, index) {

                $outPorts.append(V(portTemplate({ id: index, port: port })).node);
            });
        }, 
        //::: End renderPortst function :::

        //::: Start update function
        update: function () {
            // First render ports so that `attrs` can be applied to those newly created DOM elements
            // in `ElementView.prototype.update()`.
            this.renderPorts();
            joint.dia.ElementView.prototype.update.apply(this, arguments);
        },
        //::: End update function :::

        //::: Start updateBox function
        updateBox: function() {
            // Set the position and dimension of the box so that it covers the JointJS element.
            var bbox = this.model.getBBox();
            // Example of updating the HTML with a data stored in the cell model.
            // paper.on('blank:pointerdown', function(evt, x, y) { this.$box.find('textarea').toBack(); });
            this.model.on('cell:pointerclick', function(evt, x, y) { this.$box.find('textarea').toFront(); });
            this.$box.css({ width: bbox.width, height: bbox.height, left: bbox.x + 15, top: bbox.y, transform: 'rotate(' + (this.model.get('angle') || 0) + 'deg)' });
        },
        //::: End updateBox function :::

        //::: Start removeBox function :::
        removeBox: function(evt) {
            this.$box.remove();
        }
        //::: End removeBox function :::

    });

// -------------------------------------------------------------------------------------------------------------------------------------


// Create JointJS elements and add them to the graph as usual.
// -------------------------------------------------------------------------------------------------------------------------------------

    var system = new joint.shapes.html.Element({
        position: { x: 80, y: 80 },
        size: { width: 240, height: 180 },
        outPorts:['systemOut'],
        inPorts: ['systemIn'],  
    });

    var dbo = new joint.shapes.html.Element({
        position: { x: 120, y: 210 },
        size: { width: 240, height: 180 },
        outPorts:['dboOut'],
        inPorts: ['dboIn'],
    })
// -------------------------------------------------------------------------------------------------------------------------------------

//Adding all to the graph
    graph.addCells([system, dbo]);

}())

您可以将模板定义放在模型上,然后您可以使用自定义模板实例化元素,如下所示:

new joint.shapes.html.Element({
      template: [
            '<div class="my-html-element">',
            '<div><input data-attribute="myinput" type="checkbox"/></div>',
            '<div><input data-attribute="myinput" type="checkbox"/></div>',
            '<div><input data-attribute="myinput" type="checkbox"/></div>',
            '</div>'
        ].join(''),
});

这是一个完整的例子:https://jsfiddle.net/vtalas/pruz7h9w/

请注意,自 Joint v1.0 以来,有一个新的 API 可以更轻松地操作端口(它也应用于上面的演示中)。