11

What I am trying to do is make a element with custom class for ports and path so that I can add an element with custom path and my own markup for ports.This way when I create an element I will pass dynamic path for its shape just like elements of path class behave and as I have also extended from PortsModelInterface I will also have my own markup for ports. This whole effort is to make svg scalable for zomming. Previously I was using html custom element with my custom ports which was working fine but html of custom elements wasn't scaling on zooming

var graph = new joint.dia.
var paper = new joint.dia.Paper({
    el: $('#paper'),
    width: 800,
    height: 600,
    gridSize: 1,
    model: graph,
    snapLinks: true,
    embeddingMode: true
});
joint.shapes.custom1={};
 joint.shapes.custom1.Element = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
        markup: '<g class="rotatable"><g class="scalable"><rect class = "myrect"/></g><g class="inPorts"/><g class="outPorts"/></g>',
        portMarkup: '<g class="port<%= id %>"><circle class="port-body"/></g>',
        defaults: joint.util.deepSupplement({
            type: 'html.Element',
            size: { width: 200, height: 110 },
            inPorts: [],
            outPorts: [],
            attrs: {
                '.': { magnet: true},
                rect: {
                    stroke: 'none', 'fill-opacity': 0, width: 300, height: 210,
                },
                circle: {
                    r: 6, //circle radius
                    magnet: true,
          left:0,
                    stroke: 'gray'
                },

                '.inPorts circle': { fill: 'gray', magnet: 'passive', type: 'input', y: 0},
                '.outPorts circle': { fill: 'gray', 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-x': (index + 1) * (0.55 / total)};
            if (selector === '.outPorts') { 
          attrs[portSelector]['ref-dy'] = 15; 
      }
            return attrs;
        }
    }));
joint.shapes.custom1.Atomic = joint.shapes.custom1.Element.extend({

    markup: '<g class="rotatable"><g class="scalable"><path/></g><text/></g>',

    defaults: joint.util.deepSupplement({

        type: 'basic.Path',
        size: { width: 60, height: 60 },
        attrs: {
            'path': { fill: '#FFFFFF', stroke: 'black' },
            'text': { 'font-size': 14, text: '', 'text-anchor': 'middle', 'ref-x': .5, 'ref-dy': 20, ref: 'path', 'y-alignment': 'middle', fill: 'black', 'font-family': 'Arial, helvetica, sans-serif' }
        }
    }, joint.shapes.basic.Generic.prototype.defaults)

});

var a2 = new joint.shapes.custom1.Atomic({
    position: { x: 50, y: 260 },
    size: { width: 100, height: 100 },
    attrs: {
        path: { d: 'M 30 0 L 60 30 30 60 0 30 z' },
        text: {
            text: 'Diamond',
            'ref-y': .5 // basic.Path text is originally positioned under the element
        }
    },
     inPorts: ['in'],
     outPorts: ['out']
});
graph.addCells([a2])

The element is added in graph but some how the ports don't show up. I don't have proper concept of adding classes so please any help will be greatly appreciated. Thanks. Fiddle example

Achilles
  • 519
  • 7
  • 27
  • What does this have to do with `backbone.js`? – ivarni Jul 12 '15 at 13:29
  • 2
    Joint.js is built over backbone.js, this whole mechanism of extending classes is derived from backbone. Should'nt I add this tag?? – Achilles Jul 12 '15 at 13:38
  • 1
    Is there anyway you could make a fiddle or something so we can run the code and see it fail, and then try things to see if we can make it work? I'm not sure you're going to find someone with joint.js, but if you give us a chance to play, we may figure it out. – Guy Schalnat Jul 16 '15 at 02:58
  • 1
    Just made a fiddle of it. link is in post. – Achilles Jul 16 '15 at 10:58
  • Here's a [JSFiddle](http://jsfiddle.net/bn3p1ckj/) of a working demo of a custom element with custom ports. – c.hill Jul 24 '15 at 10:48
  • Thanks for helping but I want to give element custom path. So that I can draw elements of my choice like in a fiddle of diamond shape it can be of any shape. In your fiddle where can I give path. – Achilles Jul 26 '15 at 16:36
  • with custom markup for ports I also want to give custom markup for my element. I am not going to draw same element always. – Achilles Jul 26 '15 at 17:36
  • Did you try modifying the example in the jsfiddle I posted? Making custom shapes in jointjs is not the easiest or most intuitive thing to do right now. And working with ports is even trickier. Improving the API and usability of jointjs is on the development roadmap. – c.hill Jul 27 '15 at 08:35
  • Yes I tried. In markup for element instead of I added '', so that I can give custom d value for my variable shape element. But when I applied paper.scale function to zoom in . I was not able to draw link properly from port. [tweaked fiddle](http://jsfiddle.net/tahir_pucit_7/bn3p1ckj/1/) – Achilles Jul 27 '15 at 09:55

1 Answers1

6

I suggest to define an element with custom markup for the shape and ports. Both markups should contain an SVG path, so you can set an arbitrary path data d via model.attr() on them.

joint.shapes.devs.GenericModel = joint.shapes.devs.Model.extend({

    markup: '<g class="rotatable"><g class="scalable"><path class="body"/></g><text class="label"/><g class="inPorts"/><g class="outPorts"/></g>',
    portMarkup: '<g class="port port<%= id %>"><path class="port-body"/><text class="port-label"/></g>',

    defaults: joint.util.deepSupplement({
        type: 'devs.GenericModel'
    }, joint.shapes.devs.Model.prototype.defaults)
});

Tell the paper to use devs.ModelView for rendering.

joint.shapes.devs.GenericModelView = joint.shapes.devs.ModelView;

Now you can set or change d attribute for the shape and ports anytime you wish.

var model = new joint.shapes.devs.GenericModel({
    attrs: {
        '.body': { d: 'M 0 0 0 50 50 50 z'},
        '.port-body': { d: 'M 0 0 10 0 10 10 0 10 z'}
    } 
});

model.attr('.body/d', 'M 25 0 50 50 0 50 z');

JS Fiddle: http://jsfiddle.net/kumilingus/kge023bc/

Roman
  • 1,652
  • 11
  • 15