JointJS has built-in elements for basic shapes. These shapes are all in the joint.shapes.basic
namespace and consist of joint.shapes.basic.Rect
, joint.shapes.basic.Circle
,
joint.shapes.basic.Text
and joint.shapes.basic.Image
. Additionally,
JointJS has plugins that contain shapes and links for elements of some well-known diagrams. Though there
is plenty of shapes to choose from, you might be missing one and want to create your own.
Creating new shapes is quite simple though you need some basic knowledge of SVG elements. The most important
SVG elements you should know about
are rect
, text
, circle
, ellipse
, image
and
path
. Their thorough description
together with examples can be found e.g. on MDN.
Combining these, you can make basically any 2D shape you like.
As it was mentioned, custom elements are created by combining SVG tags. Many times, it is useful to position
one
element relatively to another. Imagine a basic situation where you want to have a rectangle element and a
text element that should always be in the center of the rectangle.
Unfortunately, SVG does not provide a facility to do that. Therefore, JointJS introduces
special attributes that are helpful for positioning elements relatively
to each other. For an example, let's explore how the
joint.shapes.basic.Rect
element is defined:
joint.shapes.basic.Rect = joint.shapes.basic.Generic.extend({
markup: '<g class="rotatable"><g class="scalable"><rect/></g><text/></g>',
defaults: joint.util.deepSupplement({
type: 'basic.Rect',
attrs: {
'rect': { fill: 'white', stroke: 'black', 'follow-scale': true, width: 80, height: 40 },
'text': { 'font-size': 14, 'ref-x': .5, 'ref-y': .5, ref: 'rect', 'y-alignment': 'middle', 'x-alignment': 'middle' }
}
}, joint.shapes.basic.Generic.prototype.defaults)
});
As you can see, the SVG tags are stored in a property markup
. This property contains an SVG
template for the joint.shapes.basic.Rect
element.
There are two important SVG groups in the markup that JointJS understands. The first one is the one with the
class "rotatable"
. All elements
in this group will get rotated when the joint.dia.Element.rotate()
method is called.
The other group is "scalable"
. All elements in this group will get scaled when
the joint.dia.Element.resize() method is called.
All the positioning and presentation definitions are then stored as usual in the attrs
object.
Notice
the special attributes ref-x
, ref-y
, ref
, x-alignment
and y-alignment
.
ref-x
and ref-y
determine the position of the text
SVG element
relative to
an element referenced to by the selector stored in the ref
attribute. In our case, the text
element is positioned 50% in the x-axis and 50% in the y-axis relative to the rect
element,
i.e. in the center of the rectangle.
x-alignment === 'middle'
and y-alignment === 'middle'
causes the text to center
itself around its x-axis and y-axis. If we didn't do that,
only the left-corner of the text element would be in the center of the rectangle but not the whole text.
Notice that in this case, we don't want the text to scale, only the rectangle (that's why the text is not inside the "scalable" group in the markup). But because we set the relative positioning attributes on the text, the text will move in order to put itself to the center of the rectangle even though the center moved due to the scale operation on the rectangle. Isn't this nice?
SVG + JointJS relative positioning attributes make it easy to create custom elements in a declarative fashion. It just needs a little bit of practice and try-fail loops.
Browse through the menu on the left to see some common techniques that you might find useful in your applications.