SVG vs. Canvas on Trivial Drawing Application

SVG Open 2009

Samuli Kaipiainen

University of Helsinki
Department of Computer Science

Matti Paksula

University of Helsinki
Department of Computer Science

Workshop!

"User interface prototype to SVG web app with rapid prototyping"

Abstract

Canvas examples

SVG examples

Illustrating the difference with a...

  1. pixel drawing application with SVG
  2. pixel drawing application with Canvas
  3. vector drawing application with SVG
  4. vector drawing application with Canvas

Pixels

PIXEL draw

Canvas

function drawPixel(canvas, x, y) {
  var ctx = canvas.getContext("2d");
  ctx.fillRect(x, y, 1, 1);
}

SVG

function drawPixel(SVGRoot, x, y) {

  var pixel = document.createElementNS(
    "http://www.w3.org/2000/svg", "rect");

  pixel.setAttribute('style', "fill: black");
  pixel.setAttribute('x', x);
  pixel.setAttribute('y', y);
  pixel.setAttribute('width', 1);
  pixel.setAttribute('height', 1);

  SVGRoot.appendChild(pixel);
}

Conclusions for pixels

Vectors

Vector drawing

SVG

// same code as when emulating pixels!

function addCircle(SVGRoot, radius, x, y) {

  var circle = document.createElementNS(
    "http://www.w3.org/2000/svg", "circle");

  circle.setAttribute('style', black);
  circle.setAttribute('cx', x);
  circle.setAttribute('cy', y);
  circle.setAttribute('r', radius);

  SVGRoot.appendChild(circle);
}

Canvas (CakeJS library)

// CakeJS is 7500 lines of JavaScript!

function addCircle(cakeCanvas, radius, x, y) {

  var circle = new Circle(radius,
    { x: x, y: y, fill: black });

  cakeCanvas.append(circle);
}

Conclusions for vectors

Recap

Combining SVG and Canvas

svg and canvas friends

Canvas to SVG

foreignObject vs. toDataURL()

Vector drawing

Using canvas.toDataURL()

function importCanvas(sourceCanvas, targetSVG) {

  // get base64 encoded png from Canvas
  var image = sourceCanvas.toDataURL();

  // Create new SVG Image element.
  var svgimg = document.createElementNS(
           "http://www.w3.org/2000/svg",
           "image");
  svgimg.setAttributeNS(
           "http://www.w3.org/1999/xlink",
           "xlink:href",
           image);

  // Append image to SVG
  targetSVG.appendChild(svgimg);
}

SVG to Canvas

Vector drawing

Server-side conversion with ImageMagick

<?php

// Save SVG from POST
$svg_xml = $_POST["svg_xml"];
file_put_contents("input.svg",$svg_xml);

// Run conversion program (ImageMagick) 
system("convert input.svg output.png");

// Return the name of rasterization for client
echo "output.png"

?>

Loading converted Image with Ajax (jQuery)

function importSVG(sourceSVG, targetCanvas) {

  var svg_xml = (new XMLSerializer()).serializeToString(sourceSVG);

  $.post("convert.php", { svg_xml: svg_xml },
    function(data) {
      var ctx = targetCanvas.getContext('2d');
      var img = new Image();

      img.onload = function() {
        ctx.drawImage(img,0,0);
        img.src = data;
      }
    });
}

Everything combined

Combined

Existing components with the same interface

SVG-edit + CanvasPaint

No vs. situation

Conclusion

shape stacking