2. Who am I?
@kangax
perfectionkills.com kangax.github.com/es5-compat-table/
3. fabric.js
Fabric.js is a framework
that makes it easy to work
with HTML5 canvas element.
It is an interactive object model
on top of canvas element.
It is also an SVG-to-canvas parser.
4. t
ian
Canvas? -co
m pl
WHATWG says:
“The canvas element provides scripts with
a resolution-dependent bitmap canvas,
which can be used for rendering graphs,
game graphics, or other visual images on
the fly.”
http://www.whatwg.org/specs/web-apps/current-work/
multipage/the-canvas-element.html#the-canvas-element
12. But wait, there’s more!
Object manipulations with mouse
http://kangax.github.com/fabric.js/test/demo/
13. Goals
• Unit tested (1000+ tests at the moment)
• Modular (~20 small "classes")
• Cross-browser (degrades gracefully)
• Fast
• Encapsulated in one object
• No browser sniffing
• ES5 strict mode -ready
14. Supported browsers
• Firefox 2+
• Safari 3+
• Opera 9.64+
• Chrome (all versions should work)
• IE9 (IE7/8 via excanvas)
15. How fabric works
“Hello world” example
var canvas = new fabric.Element('canvas');
var text = new fabric.Text('hello world', {
fontfamily: 'delicious_500'
});
canvas.add(text);
16. How fabric works
“Hello world” example
var canvas = new fabric.Element('canvas');
var text = new fabric.Text('hello world', {
fontfamily: 'delicious_500'
});
canvas.add(text);
text.setText('trololololo')
.set('left', 100)
.set('top', 100)
.set('fontfamily', 'comic_sans');
17. How fabric works
“Hello world” example
var canvas = new fabric.Element('canvas');
var text = new fabric.Text('hello world', {
fontfamily: 'delicious_500'
});
canvas.add(text);
text.setText('trololololo')
.set('left', 100)
.set('top', 100)
.set('fontfamily', 'comic_sans');
canvas.remove(text);
19. How fabric works
“Class” hierarchy
fabric.Object clone
cloneAsImage
complexity
get
fabric.Line getCenter
fabric.Circle getWidth
fabric.Triangle getHeight
intersectsWithObject
fabric.Ellipse isActive
fabric.Rect isType
fabric.Polyline scale
scaleToHeight
fabric.Polygon scaleToWidth
fabric.Group set
fabric.Text setActive
straighten
fabric.Image toDataURL
fabric.Path toJSON
...
20. How fabric works
“Class” hierarchy
clone
fabric.Object cloneAsImage
complexity
get
getCenter
fabric.Line getRadiusX
fabric.Circle getRadiusY
fabric.Triangle getWidth
getHeight
fabric.Ellipse intersectsWithObject
fabric.Rect isActive
fabric.Polyline isType
scale
fabric.Polygon scaleToHeight
fabric.Group scaleToWidth
fabric.Text set
setActive
fabric.Image straighten
fabric.Path toDataURL
toJSON
...
21. How fabric works
“Class” hierarchy
clone
fabric.Object cloneAsImage
complexity
get
getCenter
fabric.Line getWidth
getElement
fabric.Circle getHeight
fabric.Triangle intersectsWithObject
fabric.Ellipse isActive
isType
fabric.Rect scale
fabric.Polyline scaleToHeight
fabric.Polygon scaleToWidth
set
fabric.Group setActive
fabric.Text setElement
fabric.Image straighten
toDataURL
fabric.Path toJSON
toGrayscale
...
22. How fabric works
fabric.Element
add
bringForward
fabric.Element bringToFront
centerObjectH
centerObjectV
clear
clone
Main drawing area complexity
containsPoint
deactivateAll
- Wraps <canvas> element getActiveObject
- Renders fabric.* objects added to it getCenter
- Provides mouse-based selection getHeight
getWidth
- Dispatches events getObjects
insertAt
isEmpty
item
loadFromJSON
loadSVGFromURL
remove
renderAll
...
23. How fabric works
fabric.Element
render()
fabric.Rect.prototype.render render()
fabric.Path.prototype.render
render()
render() fabric.Image.prototype.render
fabric.Circle.prototype.render
24. How fabric works
Drawing a frame
1. clear entire canvas
2. for each object in canvas
2a. object.render()
render() render()
fabric.Rect.prototype.render fabric.Path.prototype.render
render()
render() fabric.Image.prototype.render
fabric.Circle.prototype.render
25. How fabric works
Prototypal inheritance
function createClass() {
var parent = null,
based on
properties = slice.call(arguments, 0); Prototype.js
if (typeof properties[0] === 'function') {
parent = properties.shift();
}
function klass() {
this.initialize.apply(this, arguments);
}
klass.superclass = parent;
klass.subclasses = [ ];
if (parent) {
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}
for (var i = 0, length = properties.length; i < length; i++) {
addMethods(klass, properties[i]);
}
if (!klass.prototype.initialize) {
klass.prototype.initialize = emptyFunction;
}
klass.prototype.constructor = klass;
return klass;
}
30. How fabric works
SVG parser
fabric.Path.prototype.render (line 173)
case 'C': // bezierCurveTo, absolute
x = current[5]; {
y = current[6]; path: [
controlX = current[3]; [ "M", -122.304, 84.285 ],
controlY = current[4]; [ "C", -122.304, 84.285,
ctx.bezierCurveTo( -122.203, 86.179,
current[1] + l,
current[2] + t, -123.027, 86.16 ],
controlX + l, [ "C", -123.851, ... ],
controlY + t, [ ... ],
x + l, ...
y + t ]
); }
break;
31. How fabric works
SVG parser
Static fromElement method on all constructors
fabric.Line.fromElement = function(element, options) {
var parsedAttributes = fabric.parseAttributes(element,
fabric.Line.ATTRIBUTE_NAMES);
var points = [
parsedAttributes.x1 || 0,
parsedAttributes.y1 || 0,
parsedAttributes.x2 || 0,
parsedAttributes.y2 || 0
];
return new fabric.Line(points,
extend(parsedAttributes, options));
};
32. How fabric works
SVG parser
Static fromElement method on all constructors
fabric.Path.fromElement = function(element, options) {
var parsedAttributes = fabric.parseAttributes(element,
fabric.Path.ATTRIBUTE_NAMES);
return new fabric.Path(parsedAttributes.d,
extend(parsedAttributes, options));
};
Ditto for fabric.Rect, fabric.Circle, etc.