Fabric.js
Bulding a canvas library




       @kangax ✎ BK.js ✎ 2011
Who am I?
                 @kangax




perfectionkills.com        kangax.github.com/es5-compat-table/
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.
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
Canvas



Charts         Games




Editors   Physics simulation
How canvas works
          document.getElementById(‘canvas’).getContext(‘2d’)
                        CanvasRenderingContext2D



• clearRect()                                      •   arc()
• fillRect()            •   drawImage()
                       •   createImageData()       •   arcTo()
• strokeRect()                                     •   bezierCurveTo()
                       •   putImageData()
                       •   getImageData()          •   clip()
                                                   •   closePath()
• restore()                                        •   fill()
• save()               • strokeText()              •   lineTo()
                       • fillText()                 •   moveTo()
•   rotate()           • measureText()             •   quadraticCurveTo()
•   scale()                                        •   rect()
•   transform()                                    •   stroke()
•   translate()        • strokeStyle=
                       • fillStyle=
But why get rid of an
 elegant canvas API for
some questionable blob of
    Javascript code?
fabric vs. native
native

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




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);
fabric vs. native
native

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


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);
fabric vs. native
native

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




fabric

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

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

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




fabric

rect.set(‘left’, 20).set(‘top’, 50);
canvas.renderAll();
But wait, there’s more!
      Object manipulations with mouse




     http://kangax.github.com/fabric.js/test/demo/
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
Supported browsers

• Firefox 2+
• Safari 3+
• Opera 9.64+
• Chrome (all versions should work)
• IE9 (IE7/8 via excanvas)
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);
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');
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);
How fabric works
                  “Class” hierarchy


fabric.Object
                                                 fabric.util.*
                     fabric.Element
fabric.Line
fabric.Circle
fabric.Triangle    fabric.parseAttributes
fabric.Ellipse     fabric.parseElements
fabric.Rect        fabric.parseStyleAttribute
fabric.Polyline    fabric.parsePointsAttribute
fabric.Polygon
fabric.Group
fabric.Text
fabric.Image                                     fabric.Color
fabric.Path         fabric.PathGroup             fabric.Point
                                                 fabric.Intersection
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
                                 ...
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
                                 ...
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
                                 ...
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
                                           ...
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
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
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;
}
How fabric works
                         Prototypal inheritance

fabric.Path = fabric.util.createClass( fabric.Object, {

 type: 'path',

 initialize: function(path, options) {
   options = options || { };
   ...
 },

 render: function() {
   ...
 },

  toString: function() {
    return '#<fabric.Path (' + this.complexity() + '): ' +
     JSON.stringify({ top: this.top, left: this.left }) + '>';
  }
});
How fabric works
     SVG parser
How fabric works
                                     SVG parser




<path d="M-122.304 84.285C-122.304        {
84.285 -122.203 86.179 -123.027               path: [
86.16C-123.851 86.141 -140.305                 [ "M", -122.304, 84.285 ],
38.066 -160.833 40.309C-160.833                [ "C", -122.304, 84.285,
40.309 -143.05 32.956 -122.304                      -122.203, 86.179,
84.285z" />
                                                         -123.027, 86.16 ],
                                                  [ "C", -123.851, ... ],
                                                  [ ... ],
                                                  ...
                                              ]
                                          }
How fabric works
                                SVG parser




                                         {
                                             path: [
                                              [ "M", -122.304, 84.285 ],
                                              [ "C", -122.304, 84.285,
            Instance of fabric.Path                -122.203, 86.179,

[[Prototype]] == fabric.Path.prototype                  -123.027, 86.16 ],
                                                 [ "C", -123.851, ... ],
                                                 [ ... ],
                                                 ...
                                             ]
                                         }
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;
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));
};
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.
http://www.w3.org/TR/SVG/
 paths.html#PathDataBNF     Fun with SVG parsing
continued...
are we there yet?
Fun with SVG parsing
Docs
http://kangax.github.com/fabric.js/docs
Unit tests
http://kangax.github.com/fabric.js/test/unit/suite_runner
Benchmarks

                                           http://kangax.github.com/fabric.js/test/
                                              raphael_vs_fabric/simple_shapes




http://kangax.github.com/fabric.js/test/
   raphael_vs_fabric/complex_shape
Future plans:
• Smaller footprint (delete Cufon)
• Custom builder
• Better docs
• More complete SVG parsing
• toSVG()
• Pretty website, logo (help!!111)
• Better IE support
These slides online:



http://slideshare.net/kangax
Thank you!
       Questions?
    http://spkr8.com/t/7303




github.com/kangax/fabric.js

@FabricJS




  Follow me @kangax

More Related Content

PDF
Fabric.js @ Falsy Values
PDF
Interactive web with Fabric.js @ meet.js
PPTX
Fabricjs ppt
PPTX
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
PDF
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
PDF
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
PDF
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
PDF
임태현, 게임 서버 디자인 가이드, NDC2013
Fabric.js @ Falsy Values
Interactive web with Fabric.js @ meet.js
Fabricjs ppt
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
Amazon RDS Proxy 집중 탐구 - 윤석찬 :: AWS Unboxing 온라인 세미나
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
임태현, 게임 서버 디자인 가이드, NDC2013

What's hot (20)

PDF
7. 게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...
PPTX
게임 분산 서버 구조
PDF
당근마켓 고언어 도입기, 그리고 활용법
PDF
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
PDF
천만 사용자를 위한 AWS 클라우드 아키텍처 진화하기::이창수::AWS Summit Seoul 2018
PDF
React JS - Introduction
PDF
쉽게 쓰여진 Django
PDF
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
PPTX
REST API 설계
PDF
혼자서 만드는 MMO게임 서버
PDF
webservice scaling for newbie
PDF
Windows IOCP vs Linux EPOLL Performance Comparison
PDF
Tomcat 마이그레이션 도전하기 (Jins Choi)
PDF
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
PDF
쿠키런 1년, 서버개발 분투기
PDF
Windows Registered I/O (RIO) vs IOCP
PDF
쿠알못이 Amazon EKS로 안정적인 서비스 운영하기 - 최용호(넥슨코리아) :: AWS Community Day 2020
PDF
Fault Tolerance 패턴
PDF
객체지향 개념 (쫌 아는체 하기)
PDF
쿠키런: 킹덤 대규모 인프라 및 서버 운영 사례 공유 [데브시스터즈 - 레벨 200] - 발표자: 용찬호, R&D 엔지니어, 데브시스터즈 ...
7. 게임 스트리밍 서비스를 위한 아키텍처 - 언리얼 엔진을 중심으로! [레벨 300] - 발표자: 하흥수, 솔루션즈 아키텍트, AWS :...
게임 분산 서버 구조
당근마켓 고언어 도입기, 그리고 활용법
[야생의 땅: 듀랑고] 서버 아키텍처 Vol. 2 (자막)
천만 사용자를 위한 AWS 클라우드 아키텍처 진화하기::이창수::AWS Summit Seoul 2018
React JS - Introduction
쉽게 쓰여진 Django
오딘: 발할라 라이징 MMORPG의 성능 최적화 사례 공유 [카카오게임즈 - 레벨 300] - 발표자: 김문권, 팀장, 라이온하트 스튜디오...
REST API 설계
혼자서 만드는 MMO게임 서버
webservice scaling for newbie
Windows IOCP vs Linux EPOLL Performance Comparison
Tomcat 마이그레이션 도전하기 (Jins Choi)
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
쿠키런 1년, 서버개발 분투기
Windows Registered I/O (RIO) vs IOCP
쿠알못이 Amazon EKS로 안정적인 서비스 운영하기 - 최용호(넥슨코리아) :: AWS Community Day 2020
Fault Tolerance 패턴
객체지향 개념 (쫌 아는체 하기)
쿠키런: 킹덤 대규모 인프라 및 서버 운영 사례 공유 [데브시스터즈 - 레벨 200] - 발표자: 용찬호, R&D 엔지니어, 데브시스터즈 ...
Ad

Viewers also liked (20)

PDF
Open Source - Hip not Hype
PDF
The Use of Creative Commons Licences in the Ministry of Justice of the Govern...
PDF
The Desirability of Connected Products
PDF
Guide open source-bdef
PDF
towards a global CC license - the affiliate perspective
KEY
Creative Commons Enforcement
PDF
Open Source and Economic Development
PPT
Using the CC BY license, Workshop for 2013 OPEN Kick-off
KEY
CCL and Database in Korea
PPT
Phillips Remix Cycle Pixelodeon 2007
ODP
The definition and future of noncommercial
KEY
The HTML5 WebSocket API
PPTX
Open Credential and Radical Openness
PPTX
Saudi Arabia’s National Open Education Strategy, Master Plan & Policy
PPTX
Creative Commons & Cultural Heritage
PDF
Hong Kong Startup Ecosystem ToolBox v.1
PPTX
Planning of lutyens' delhi
PPTX
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
PPTX
Made With Creative Commons
PPTX
Creative Commons Certificates
Open Source - Hip not Hype
The Use of Creative Commons Licences in the Ministry of Justice of the Govern...
The Desirability of Connected Products
Guide open source-bdef
towards a global CC license - the affiliate perspective
Creative Commons Enforcement
Open Source and Economic Development
Using the CC BY license, Workshop for 2013 OPEN Kick-off
CCL and Database in Korea
Phillips Remix Cycle Pixelodeon 2007
The definition and future of noncommercial
The HTML5 WebSocket API
Open Credential and Radical Openness
Saudi Arabia’s National Open Education Strategy, Master Plan & Policy
Creative Commons & Cultural Heritage
Hong Kong Startup Ecosystem ToolBox v.1
Planning of lutyens' delhi
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Made With Creative Commons
Creative Commons Certificates
Ad

Similar to Fabric.js — Building a Canvas Library (20)

PPTX
HTML5 Graphics - Canvas and SVG
PPTX
Building Windows 8 Metro Style casual games using HTML5 and JavaScript
PDF
Exploring Canvas
PDF
HTML5 Canvas - The Future of Graphics on the Web
PDF
Power of canvas
PDF
HTML5 Canvas
KEY
Exploring Canvas
PDF
MS TechDays 2011 - HTML 5 All the Awesome Bits
PDF
HTML5って必要?
PDF
html5 Canvas element
PDF
How to build a html5 websites.v1
PPT
HTML5 Canvas
PDF
SVGo workshop
KEY
The Canvas API for Rubyists
PDF
Desingning reusable web components
PDF
SVGo: a Go Library for SVG generation
PDF
Desingning reusable web components
PDF
High Performance Mobile Web Game Development in HTML5
PDF
Intro to HTML5 Canvas
HTML5 Graphics - Canvas and SVG
Building Windows 8 Metro Style casual games using HTML5 and JavaScript
Exploring Canvas
HTML5 Canvas - The Future of Graphics on the Web
Power of canvas
HTML5 Canvas
Exploring Canvas
MS TechDays 2011 - HTML 5 All the Awesome Bits
HTML5って必要?
html5 Canvas element
How to build a html5 websites.v1
HTML5 Canvas
SVGo workshop
The Canvas API for Rubyists
Desingning reusable web components
SVGo: a Go Library for SVG generation
Desingning reusable web components
High Performance Mobile Web Game Development in HTML5
Intro to HTML5 Canvas

Recently uploaded (20)

PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
Taming the Chaos: How to Turn Unstructured Data into Decisions
PDF
NewMind AI Weekly Chronicles – August ’25 Week III
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PPT
What is a Computer? Input Devices /output devices
PDF
1 - Historical Antecedents, Social Consideration.pdf
PPTX
Final SEM Unit 1 for mit wpu at pune .pptx
PDF
A Late Bloomer's Guide to GenAI: Ethics, Bias, and Effective Prompting - Boha...
PPTX
Chapter 5: Probability Theory and Statistics
PDF
August Patch Tuesday
PDF
Unlock new opportunities with location data.pdf
PDF
A novel scalable deep ensemble learning framework for big data classification...
PPT
Geologic Time for studying geology for geologist
PPTX
Benefits of Physical activity for teenagers.pptx
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
CloudStack 4.21: First Look Webinar slides
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PDF
Hindi spoken digit analysis for native and non-native speakers
PPTX
Web Crawler for Trend Tracking Gen Z Insights.pptx
Assigned Numbers - 2025 - Bluetooth® Document
Zenith AI: Advanced Artificial Intelligence
Taming the Chaos: How to Turn Unstructured Data into Decisions
NewMind AI Weekly Chronicles – August ’25 Week III
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
What is a Computer? Input Devices /output devices
1 - Historical Antecedents, Social Consideration.pdf
Final SEM Unit 1 for mit wpu at pune .pptx
A Late Bloomer's Guide to GenAI: Ethics, Bias, and Effective Prompting - Boha...
Chapter 5: Probability Theory and Statistics
August Patch Tuesday
Unlock new opportunities with location data.pdf
A novel scalable deep ensemble learning framework for big data classification...
Geologic Time for studying geology for geologist
Benefits of Physical activity for teenagers.pptx
Enhancing emotion recognition model for a student engagement use case through...
CloudStack 4.21: First Look Webinar slides
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Hindi spoken digit analysis for native and non-native speakers
Web Crawler for Trend Tracking Gen Z Insights.pptx

Fabric.js — Building a Canvas Library

  • 1. Fabric.js Bulding a canvas library @kangax ✎ BK.js ✎ 2011
  • 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
  • 5. Canvas Charts Games Editors Physics simulation
  • 6. How canvas works document.getElementById(‘canvas’).getContext(‘2d’) CanvasRenderingContext2D • clearRect() • arc() • fillRect() • drawImage() • createImageData() • arcTo() • strokeRect() • bezierCurveTo() • putImageData() • getImageData() • clip() • closePath() • restore() • fill() • save() • strokeText() • lineTo() • fillText() • moveTo() • rotate() • measureText() • quadraticCurveTo() • scale() • rect() • transform() • stroke() • translate() • strokeStyle= • fillStyle=
  • 7. But why get rid of an elegant canvas API for some questionable blob of Javascript code?
  • 8. fabric vs. native native var canvasEl = document.getElementById('canvas'); var ctx = canvasEl.getContext('2d'); ctx.strokeStyle = ''; ctx.fillStyle = 'red'; ctx.fillRect(100, 100, 20, 20); 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);
  • 9. fabric vs. native native var canvasEl = document.getElementById('canvas'); var ctx = canvasEl.getContext('2d'); ctx.strokeStyle = ''; ctx.fillStyle = 'red'; because we all love radians ctx.save(); ctx.translate(100, 100); ctx.rotate(Math.PI / 180 * 45); ctx.fillRect(-10, -10, 20, 20); ctx.restore(); 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);
  • 10. fabric vs. native native ctx.fillRect(20, 50, 20, 20); fabric rect.set(‘left’, 20).set(‘top’, 50); canvas.renderAll();
  • 11. fabric vs. native native ctx.fillRect(20, 50, 20, 20); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); ctx.fillRect(20, 50, 20, 20); fabric rect.set(‘left’, 20).set(‘top’, 50); canvas.renderAll();
  • 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);
  • 18. How fabric works “Class” hierarchy fabric.Object fabric.util.* fabric.Element fabric.Line fabric.Circle fabric.Triangle fabric.parseAttributes fabric.Ellipse fabric.parseElements fabric.Rect fabric.parseStyleAttribute fabric.Polyline fabric.parsePointsAttribute fabric.Polygon fabric.Group fabric.Text fabric.Image fabric.Color fabric.Path fabric.PathGroup fabric.Point fabric.Intersection
  • 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; }
  • 26. How fabric works Prototypal inheritance fabric.Path = fabric.util.createClass( fabric.Object, { type: 'path', initialize: function(path, options) { options = options || { }; ... }, render: function() { ... }, toString: function() { return '#<fabric.Path (' + this.complexity() + '): ' + JSON.stringify({ top: this.top, left: this.left }) + '>'; } });
  • 27. How fabric works SVG parser
  • 28. How fabric works SVG parser <path d="M-122.304 84.285C-122.304 { 84.285 -122.203 86.179 -123.027 path: [ 86.16C-123.851 86.141 -140.305 [ "M", -122.304, 84.285 ], 38.066 -160.833 40.309C-160.833 [ "C", -122.304, 84.285, 40.309 -143.05 32.956 -122.304 -122.203, 86.179, 84.285z" /> -123.027, 86.16 ], [ "C", -123.851, ... ], [ ... ], ... ] }
  • 29. How fabric works SVG parser { path: [ [ "M", -122.304, 84.285 ], [ "C", -122.304, 84.285, Instance of fabric.Path -122.203, 86.179, [[Prototype]] == fabric.Path.prototype -123.027, 86.16 ], [ "C", -123.851, ... ], [ ... ], ... ] }
  • 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.
  • 35. are we there yet?
  • 36. Fun with SVG parsing
  • 39. Benchmarks http://kangax.github.com/fabric.js/test/ raphael_vs_fabric/simple_shapes http://kangax.github.com/fabric.js/test/ raphael_vs_fabric/complex_shape
  • 40. Future plans: • Smaller footprint (delete Cufon) • Custom builder • Better docs • More complete SVG parsing • toSVG() • Pretty website, logo (help!!111) • Better IE support
  • 42. Thank you! Questions? http://spkr8.com/t/7303 github.com/kangax/fabric.js @FabricJS Follow me @kangax

Editor's Notes