Extending
Due to the Object Oriented nature of SVG.js, objects/prototypes can be extended on any level. The invent()
and extend()
methods provide a convenient way to implement your own functionality.
SVG.invent()
Creating your own custom elements with SVG.js is a piece of cake thanks to the SVG.invent
function. For the sake of this example, lets "invent" a shape. We want a rect
with rounded corners that are always proportional to the height of the element. The new shape lives in the SVG
namespace and is called Rounded
. Here is how we achieve that.
SVG.Rounded = SVG.invent({
// Define the type of element that should be created
create: 'rect'
// Specify from which existing class this shape inherits
, inherit: SVG.Shape
// Add custom methods to invented shape
, extend: {
// Create method to proportionally scale the rounded corners
size: function(width, height) {
return this.attr({
width: width
, height: height
, rx: height / 5
, ry: height / 5
})
}
}
// Add method to parent elements
, construct: {
// Create a rounded element
rounded: function(width, height) {
return this.put(new SVG.Rounded).size(width, height)
}
}
})
To create the element in your drawing:
var rounded = draw.rounded(200, 100)
That's it, the invention is now ready to be used!
Accepted values
The SVG.invent()
function always expects an object. The object can have the following configuration values.
- create
required
Can be either a string with the node name (e.g. rect
, ellipse
, ...) or a custom initializer function.
- inherit
optional
but recommended
defaults
to SVG.Element
The desired SVG.js class to inherit from (e.g. SVG.Shape
, SVG.Element
, SVG.Container
, SVG.Rect
, ...).
- extend
optional
An object with the methods that should be applied to the element's prototype.
- construct
optional
An object with the methods to create the element on the parent element.
- parent
optional
defaults
to SVG.Container
An SVG.js parent class on which the methods in the passed construct
object should be available.
Usage notes
It should be emphasised that in the configuration object passed to SVG.invent()
:
construct
does not supply constructors, but rather methods that are likely to call constructors;create
specifies the constructor for the type you are defining, and is not analogous toObject.create()
.
When defining specialised svg elements (such as SVG.Rounded
in the example above), the function specified by create
needs to do all the work of adding the element to the DOM for the svg document and connecting the DOM node to the SVG.js interface. All this is done automatically when the value of create
is a string identifying an element type. If needed, see the source for a sense of how to do it explicitly.
Though the defaults are geared toward creating svg elements for the SVG.js framework, SVG.invent()
can be used as a generalised function for defining types in Javascript. When used in this more general way, the function supplied as a value for create
should be written as an ordinary JS constructor. (Indeed, the function is simply returned as the constructor for your newly defined type.)
Svg.js uses the SVG.invent()
function to create all internal elements. A look at the source will show how this function is used in various ways.
SVG.extend()
SVG.js has a modular structure. It is very easy to add your own methods at different levels. Let's say we want to add a method to all shape types then we would add our method to SVG.Shape
:
SVG.extend(SVG.Shape, {
paintRed: function() {
return this.fill('red')
}
})
Now all shapes will have the paintRed()
method available. Say we want to have the paintRed()
method on an ellipse apply a slightly different colour:
SVG.extend(SVG.Ellipse, {
paintRed: function() {
return this.fill('orangered')
}
})
The complete inheritance stack for SVG.Ellipse
is:
SVG.Element
>
SVG.Shape
>
SVG.Ellipse
The SVG document can be extended by using:
SVG.extend(SVG.Doc, {
paintAllPink: function() {
this.each(function() {
this.fill('pink')
})
}
})
You can also extend multiple elements at once:
SVG.extend(SVG.Ellipse, SVG.Path, SVG.Polygon, {
paintRed: function() {
return this.fill('orangered')
}
})