SVG and Canvas:
Graphics for Web Apps

Vladimir Vukićević

Mozilla Corporation

Web Apps?

  • Bugzilla: Form input, server-side CGI round trip
    • Fairly ugly; lots of manual input, little or no prompting for what might be valid and what's not
  • Travelocity: Prettier
    • Form entry has gotten really fancy, but it's still form entry
  • Gmail: AJAX! Lots of text being passed around, high information density.
    • User not aware of "pages"; it feels like an "app"
  • flickr: Soemone's starting to do things with graphics.
    • Very simple; just imgs. Any "complex" stuff (the simple animation viewer) get shoved into Flash.
  • The tools for doing gfx on the web has been pretty scarce.

From almost nothing...

  • Mozilla's performance graphs.
  • Server-generated image; requires round-trip if any parameters are changed.
  • Even if the client should in theory already have the data!
  • Requires CGI scripting on the server.

From almost nothing...


  • Walter Zorn's JavaScript graphics library.
  • Simple vector graphics using straight HTML elements.
    • Uses divs. Uses LOTS of divs. But can create graphics.

From almost nothing...

  • Flash
    • Last resort, but you get to last resort point quickly
    • Ubiquitous; easiest way to accomplish all sorts of stuff
    • It doesn't really play nice with the web; there are scripting bridges
  • VML
    • Microsoft's VML. IE only, 2D markup language. Precursor to SVG; what VRML is to X3D.

... to lots of options



SVG



<canvas>
  • Both SVG and Canvas started gaining traction last year
  • Mozilla shipped implementations with Firefox 1.5
  • Early adopters are experimenting with both
  • Quick comparison first, then look at SVG and canvas more closely

Which one do I use?

SVG canvas
Has scene DOM (SVG DOM, though) Single HTML element, rendering script-driven
Deals in shapes Deals in pixels
Somewhat hard to mix with HTML (not XHTML) Behaves like an image in both
Event handling easy Event handling hard
  • Big bifference: DOM
    • SVG has one, canvas doesn't
    • Retained mode vs. Immediate mode (scaling, scrolling, etc.)
    • All canvas rendering is script-driven
  • Shapes vs. Pixels
    • SVG is retained mode, canvas is immediate mode
    • canvas has no knowledge of what's drawn; they're just pixels; SVG retains the full scene layout information
    • An SVG document can be scaled/rotated etc. without any loss of resolution; a canvas requires a redraw, or it's just an image transform.
  • Integration with HTML
    • Canvas is really just a fancy type of img element, whose contents are dynamic
    • SVG can integrate well with XHTML, but it's hard to add it to straight HTML -- you end up having to use an object tag, or to create a namespaced SVG element dynamically
    • (Not so bad: if you have pre-made svg content, an object tag is ok, and if you don't, you're going to generate stuff anyway)
  • Event handling
    • Because of its DOM presence, you can attach DOM/XML event handlers directly to shape elements
    • Easy to do mouseovers, handle clicks in complex shapes, etc.
    • Hard with canvas; as it has no knowledge of actual shapes, everything's just pixels. Have to track the mouse and do your own hit tests (but this can be made easier through using imagemap-like things)

SVG

  • W3C Standard; 1.1 now, 1.2 is in progress
  • Expressive DOM
  • Lots of existing documentation; won't spend too much time on SVG

SVG Example


  <g transform="translate(250,150)">
    <g transform="translate(-82,0)">
      <rect id="square" fill="red" x="-40" y="-40" width="80" height="80"
          onmousedown="doMouseDown(evt)"/>
    </g>
    <g transform="translate(82,0)">
      <circle id="circle" fill="blue" cx="0" cy="0" r="40"
          onmousedown="doMouseDown(evt)"/>
    </g>
    <g transform="translate(0,0)">
      <polygon id="triangle" fill="green" points="-40,40 0,-40 40,40"
        onmousedown="doMouseDown(evt)"/>
    </g>
  </g>
        
  • Most content is specified through markup; can use CSS to style
  • High level primitives such as circles, rects; generic polygons
  • Event handling on individual elements through normal event mechanisms "for free"

SVG Tools

Inkscape
Adobe Illustrator
...
Export to SVG
  • Great for tools; lots of editors that generate SVG
  • It's a good 2D interchange format
  • Export-to-SVG is easy to add to many apps; there is such a thing as an "SVG Document"

SVG Limitations

  • Data-driven rendering requires heavy DOM manipulation
  • Hard to write by hand, you /need/ tools
  • It's XML, so you can copy snippets, as long as they're correct
  • Generated SVG not so good for that
  • Ian Hixon uses XBL, but you need a browser that does XBL
  • SVG 1.1 spec is relatively sane, though profiled
  • SVG 1.2 (Tiny!) spec is extremely complex
    • a lot of "optional" features that might or might be implemented, or might be implemented slowly.
    • Animation, focus, tooltips, audio/video, network socket I/O...

SVG Examples


Dojo Toolkit
  • Dojo Toolkit, SVG charting
  • Turns table markup into SVG dynamically, or shows table if SVG isn't available
  • <canvas>

    • Canvas is a programmable img element
    • Gives a surface of some specified size to draw into
    • Originally created by Apple for use in Dashboard in Tiger
    • Now part of the WHATWG Web Apps spec
    • Good multi-browser support
    • ExplorerCanvas for IE, on top of VML

    <canvas> 2D

    
    var ctx = canvas.getContext("2d");
    with (ctx) {
      translate(canvas.width / 2, canvas.height / 2);
    
      save(); translate(-82, 0);
      fillStyle = "red";
      fillRect(-40, -40, 80, 80);
      restore();
    
      save(); translate(0, 0);
      fillStyle = "green";
      beginPath();
      moveTo(-40, 40);
      lineTo(0, -40);
      lineTo(40, 40);
      fill(); restore();
    
      save(); translate(82, 0);
      fillStyle = "blue";
      arc(0, 0, 40, 0, 2 * Math.PI, false);
      fill(); restore();
    }
            
    • Canvas supports multiple contexts; first one is for 2D drawing
    • Fully programmatic API for drawing; the only element in the page markup is canvas
    • Supports 2D affine transforms (scaling, translation, rotation)
    • Core operation is path strokes/fills
    • Path build-up uses commands similar to PostScript (moveto, lineto, arc, closepath)

    <canvas> 2D: Patterns

    
    var pat = ctx.createPattern(img, "repeat");
    with (ctx) {
      fillStyle = pat;
      beginPath();          // triangle
      moveTo(10, 90);
      lineTo(50, 10);
      lineTo(90, 90);
      lineTo(10, 90);
      stroke();
    
      rotate(Math.PI/4);
      scale(.2, .2);
      fill();
    }
            
    • Drawing images
    • Single images using drawImage
    • Resuable patterns using createPattern (including image and gradient patterns)
    • canvases can be used as images!
    • offscreen images

    <canvas> 2D: Animation

    
    with (ctx) {
      var pat = createPattern(img, "repeat");
      fillStyle = pat;
      triangle(ctx); // create our triangle path
      stroke();
    
      setInterval(function () {
          // fill with transparent white, to fade out
          ctx.fillStyle = "rgba(255, 255, 255, 0.5)";
          ctx.fill();
          // rotate and fill with our pattern
          ctx.rotate(Math.PI/20);
          ctx.fillStyle = pat;
          ctx.fill();
        }, 100);
    }
            
    • Animation in canvas is done through DOM timers, just like DHTML
    • You redraw the scene (or portion of the scene) that needs to animate
    • In this example, fade out using a transparent white wash
    • Then redraw using a new rotation

    <canvas> 2D: drawWindow

    
    with (ctx) {
      translate(canvas.width/2, 0);
      scale(s, s);
      rotate(Math.PI / 4, Math.PI / 4);
    
      drawWindow(window, 0, 0, window.innerWidth,
              window.innerHeight, "#ffffff");
    
      lineWidth = 2.0;
      strokeRect(0, 0, window.innerWidth,
              window.innerHeight);
    }
            
    • drawWindow, Mozilla extension currently not available to content
    • working on getting it standardized
    • draws page contents to a canvas, with transforms
    • used by many firefox extensions for page preview
    • toDataURL for saving thumbnails

    <canvas> Limitations

    • Text rendering
      • divs
      • font textures
      • drawWindow allows for drawing a DOM window to a canvas, with transforms (can draw CSS laid-out text); privileged content only for now, spec in progress
      • Spec in progress for simple text rendering direct to canvas
    • Scene redrawing
      • Need to redraw whatever part changes
      • Can draw infrequently changing pieces into offscreen canvas, composite together

    SVG vs. <canvas> Code

    SVG

    
    var rect = document.createElementNS(SVG_NS, "rect");
    rect.setAttribute("x", "5");
    rect.setAttribute("y", "5");
    rect.setAttribute("width", "20");
    rect.setAttribute("height", "20");
    rect.setAttribute("fill", "red");
    parent.appendChild(rect);
    	

    Canvas

    
    with (ctx) {
      fillStyle = "red";
      fillRect(5, 5, 20, 20);
    }
    	
    • Dynamically drawing some shapes with svg and canvas
    • SVG more wordy and has way more internal overhead
    • Canvas code easier to understand
    • If you wanted to change the rectangle to blue, though, it's one line with SVG, but you'd have to redraw the canvas scene

    SVG vs. <canvas> Code

    SVG

    
    var poly = document.createElementNS(SVG_NS, "polygon");
    poly.setAttribute("fill", "green");
    poly.setAttribute("points", "-40,40 0,-40, 40,40");
    parent.appendChild(poly);
    	

    Canvas

    
    with (ctx) {
      fillStyle = "green";
      beginPath();
      moveTo(-40, 40);
      moveTo(0, -40);
      moveTo(40, 40);
      closePath();
      fill();
    }
    	
    • Dynamically drawing some shapes with svg and canvas
    • SVG more wordy and has way more internal overhead
    • Canvas code easier to understand
    • If you wanted to change the rectangle to blue, though, it's one line with SVG, but you'd have to redraw the canvas scene

    <canvas> Future

    • Text rendering
    • Opera additions being standardized

    <canvas> 3D

    <canvas> Examples: Borders


    Decorative Borders and the Canvas
    (Agustin Fernandez)
  • Canvas decorative borders
  • Interactive, borders expand/contract on mouseover
  • Canvas used as a dynamic background image to normal content (text)
  • <canvas> Examples: PlotKit


    PlotKit
    (Alastair Tse)
  • PlotKit, example canvas middleware
  • Built on top of MochiKit
  • Handles text through positioning divs of text
  • <canvas> Examples: NS-Tower


    NS-Tower in Canvas
    (Dan Vanderkam)
  • Game
  • <canvas> Examples: New Perf Graphs


    New Pref Graphs
  • New Perf Graphs
  • JSON pull of data, lets you focus in in real-time
  • Work in progress
  • <canvas> Examples: Everyone Loves Widgets


    Widgets!
  • Widgets!
  • Original use case for Apple's canvas
  • Most of their widgets didn't actually use canvas -- they just used really badly broken HTML that happened to work in safari
  • This could be SVG too, just happens to use canvas for the clock display, the rest is just a div with rounded borders
  • Firefox 3 (gecko/xulrunner 1.9)
  • Work in progress
  • <canvas> Examples: 3D


    3D Canvas Context
  • 3D Canvas Context
  • drawWindow to create a texture from a web page
  • Questions?

    Questions?

    Contact

    Vladimir Vukićević

    vladimir@mozilla.com

    Mozilla Corporation