Fabric.js @ Falsy Values

42
fabric.js Building a canvas library Warsaw 2011

description

Presentation on Fabric.js at Falsy Values, Warsaw, 2011

Transcript of Fabric.js @ Falsy Values

Page 1: Fabric.js @ Falsy Values

fabric.jsBuilding a canvas library

Warsaw ♥ 2011

Page 2: Fabric.js @ Falsy Values

who is kangax?kangax.com

Page 3: Fabric.js @ Falsy Values

Common Feature Tests

perfectionkills.com ES5 compat tables

HTML minifier

PrototypeJS

DOMLint

fabric.js

who is kangax?

Page 4: Fabric.js @ Falsy Values

HistoryWhy fabric?How it works. Features.Canvas librariesFuture plans

Game Plan

Page 5: Fabric.js @ Falsy Values

Historyprintio.ru

Page 6: Fabric.js @ Falsy Values

Historyprintio.ru

All Javascript, no FlashFree drawingVectors & imagesPerformance

Page 7: Fabric.js @ Falsy Values

Canvas vs SVG

Page 8: Fabric.js @ Falsy Values

Why fabric?

There was an excruciating need forinteractive object model

for canvas element

Canvas API sucks is too low level

Page 9: Fabric.js @ Falsy Values

Why fabric?

var canvas = new fabric.Element('canvas');

var rect = new fabric.Rect({ top: 100, left: 100, fill: 'red', width: 20, height: 20});

canvas.add(rect);

var canvasEl = document.getElementById('canvas');var ctx = canvasEl.getContext('2d');ctx.strokeStyle = '';ctx.fillStyle = 'red';ctx.fillRect(100, 100, 20, 20);

native

fabric

Page 10: Fabric.js @ Falsy Values

Why fabric?

var canvas = new fabric.Element('canvas');

var rect = new fabric.Rect({ top: 100, left: 100, fill: 'red', width: 20, height: 20, angle: 45});

canvas.add(rect);

var canvasEl = document.getElementById('canvas');var ctx = canvasEl.getContext('2d');ctx.strokeStyle = '';ctx.fillStyle = 'red';ctx.save();ctx.translate(100, 100);ctx.rotate(Math.PI / 180 * 45);ctx.fillRect(-10, -10, 20, 20);ctx.restore();

native

fabric

Page 11: Fabric.js @ Falsy Values

Why fabric?

rect.set(‘left’, 20).set(‘top’, 50);canvas.renderAll();

ctx.fillRect(20, 50, 20, 20);

native

fabric

Page 12: Fabric.js @ Falsy Values

Why fabric?

rect.set(‘left’, 20).set(‘top’, 50);canvas.renderAll();

ctx.fillRect(20, 50, 20, 20);

ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);ctx.fillRect(20, 50, 20, 20);

native

fabric

Page 14: Fabric.js @ Falsy Values

Under the hoodUpper <canvas>

Lower <canvas>

Group selection

All objects

Page 15: Fabric.js @ Falsy Values

Under the hood

fabric.Triangle

fabric.Circlefabric.Rect

fabric.Element

render()render()

render()

renderAll()

Page 16: Fabric.js @ Falsy Values

Under the hood

fabric.Triangle

fabric.Circlefabric.Rect

fabric.Element

render()

render()renderAll()

render()

Page 17: Fabric.js @ Falsy Values

Under the hood

fabric.Element

fabric.Object fabric.Linefabric.Circlefabric.Trianglefabric.Ellipsefabric.Rectfabric.Polylinefabric.Polygonfabric.Groupfabric.Textfabric.Imagefabric.Path

Root “class”. 2D objects

Container

Concrete “subclasses”

fabric.Colorfabric.Pointfabric.Intersection

Page 18: Fabric.js @ Falsy Values

Under the hood

fabric.Object

Root “class”. 2D objects

clonecloneAsImagecomplexitygetgetCentergetWidthgetElementgetHeightintersectsWithObjectisActiveisTypescalescaleToHeightscaleToWidthsetsetActivesetElementstraightentoDataURLtoJSONtoGrayscale...

Inherited by all subclasses

Page 19: Fabric.js @ Falsy Values

Features — Animationfabric.util.animate

fxCenterObjectV: function (...) { ...

fabric.util.animate({

startValue: object.get('top'), endValue: this.getCenter().top,

duration: this.FX_DURATION,

onChange: function(value) { object.set('top', value); _this.renderAll(); onChange(); }, onComplete: function() { object.setCoords(); onComplete(); } }); ...}

fxCenterObjectVfxCenterObjectHfxStraightenObjectfxRemove...

Page 20: Fabric.js @ Falsy Values

Features — AnimationOr just use new, fancy window.requestAnimationFrame

(function animate() { canvas.forEachObject(function(obj) { obj.left += (obj.movingLeft ? -1 : 1); obj.top += 1; if (obj.left > 900 || obj.top > 500) { canvas.remove(obj); } else { obj.setAngle(obj.getAngle() + 2); } }); canvas.renderAll(); window.requestAnimationFrame(animate);})();

Page 21: Fabric.js @ Falsy Values

Features — Eventsfabric.util.observeEvent('object:moved', function(e) {

var activeObject = e.memo.target;

console.log(activeObject.left, activeObject.top);

});

object:scaledobject:selectedobject:moved

group:modifiedgroup:selectedbefore:group:destroyedafter:group:destroyed

mouse:up

selection:clearedpath:created

Will be made more consistent!

Page 22: Fabric.js @ Falsy Values

Features — Textvar myText = new fabric.Text('Hello world', {

fontfamily: 'delicious'

});

canvas.add(myText);

fontsizefontweightfontfamilyfontStyle

textDecorationtextShadow

lineHeightbackgroundColor

strokeStylestrokeWidth

Will be made more consistent!

Page 23: Fabric.js @ Falsy Values

Features — TextMultiline support

text aligning coming soon

Page 24: Fabric.js @ Falsy Values

Features — TextMultiline supportRelies on Cufon.js

http://kangax.github.com/jstests/canvas_fillText_test

Page 25: Fabric.js @ Falsy Values

Features — TextMultiline supportRelies on Cufon.jsRenders using any OTF, TTF, etc. font

Each font is a JS file with glyph definitions

Page 26: Fabric.js @ Falsy Values

Features — SVG Parser

Q: How to render SVG shapes on canvas?

A: Transform them to fabric objects.

Page 27: Fabric.js @ Falsy Values

Features — SVG Parser

<path d="M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z" />

{ path: [ [ "M", -122.304, 84.285 ], [ "C", -122.304, 84.285, -122.203, 86.179,

-123.027, 86.16 ], [ "C", -123.851, ... ], [ ... ], ... ]}

Step 1

Page 28: Fabric.js @ Falsy Values

Features — SVG Parser

{ path: [ [ "M", -122.304, 84.285 ], [ "C", -122.304, 84.285, -122.203, 86.179,

-123.027, 86.16 ], [ "C", -123.851, ... ], [ ... ], ... ]}

case 'C': // bezierCurveTo, absolute x = current[5]; y = current[6]; controlX = current[3]; controlY = current[4]; ctx.bezierCurveTo( current[1] + l, current[2] + t, controlX + l, controlY + t, x + l, y + t ); break;

Step 2

Page 29: Fabric.js @ Falsy Values

Canvas libraries

http://goo.gl/CCRRT

Page 30: Fabric.js @ Falsy Values

Canvas libraries

canvgThe only other library with (good) SVG parserBut no object model

Page 31: Fabric.js @ Falsy Values

Canvas libraries

burstLots of features but completely abandoned

Page 32: Fabric.js @ Falsy Values

Canvas libraries

Unit TestsHard to come across a library that has them

Page 33: Fabric.js @ Falsy Values

Canvas libraries

easel.js

Probably the most active, similar, and promising alternative.But no unit tests or SVG parser :(

Page 34: Fabric.js @ Falsy Values

Fabric use cases

CollagesBasic gamesChartsBasic drawing (paintbrush, diagrams)Display SVG where unsupported (Android)

might be overkill for static charts

mouse-based interactions built in

Page 35: Fabric.js @ Falsy Values

What can you build?mustachified.com

Page 36: Fabric.js @ Falsy Values

Future plans

Smaller footprintBetter docs, tutorialsCustom builderfabric-to-SVGTouch compatible (iOS)

Page 37: Fabric.js @ Falsy Values

Smaller footprint

102 KB — minified

33 KB — minified + compressed

Fabric 0.2.5 jQuery 1.6.1

91 KB — minified

32 KB — minified + compressed

Can do even better – optional json2.js, cufon.js + custom builder

Page 38: Fabric.js @ Falsy Values

Smaller footprint

102 KB — minified

33 KB — minified + compressed

with Cufon without cufon.js

86 KB — minified

29 KB — minified + compressed

without json2.js

82 KB — minified

25 KB — minified + compressed

JSON missing in FF 3, SF 3.2, OP 10.1, IE 7

Page 41: Fabric.js @ Falsy Values

Supported browsers

Firefox 2+Safari 3+ (& Mobile Safari)Opera 9.64+Chrome (all versions should work)IE9+ (IE7 & 8 via excanvas.js)

Page 42: Fabric.js @ Falsy Values

Thank you!Questions?

github.com/kangax/[email protected]

http://spkr8.com/t/7582

@kangax