Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between the way that Canvas libraries handle SVGs and SVG libraries handle SVGs?

I am very interested in exploring graphical user interfaces in the browser. I really like .SVG files for many reasons, mainly that they are scalable and can be easily made in programs like Illustrator. The other thing I like is that in many libraries (such as Snap.svg) the individual layers can be selected (like just the circle path of a more complex shape).

However, I also frequently use particles and have many objects to draw. Because I do things that react to music I need the absolute fastest library possible (to maintain a high FPS count with many objects).

After looking at webGL and SVG and canvas, I can see that webGL is obviously the fastest for drawing things such as pictures, but I see no libraries that are able to use webGL and access the same Path information that native svg libraries have.

Could someone explain to me what the difference between "native" svg libraries and libraries that use the canvas element (such as paper.js fabric.js) with "svg parsers"? (I don't even really know what an svg parser is).

It seems that the libraries somehow draw the items to the canvas, which I believe would turn them into raster (losing the scalability and resolution independence of svgs) and I am not sure that the individual layers / paths of the svgs could still be selected (as they can be in libraries like Snap).

I would also love to know why there are no webGL based svg libraries.

Thank you

like image 850
Startec Avatar asked Nov 22 '14 00:11

Startec


1 Answers

Here's quick breakdown (disclaimer: I'm the author of Fabric.js)

SVG libraries

Raphael.js, Bonsai.js, svg.js, Snap.svg, etc.

These use SVG as the underlying technology to render graphics. This is vector graphics. They are both abstractions and "gateways" that allow you to execute something like this (example from Bonsai):

var shape1 = new Rect(10,10,100,100).attr({fillColor: 'red'});
var group = new Group();
group.addChild(shape1);

stage.addChild(group);

and get this:

<svg data-bs-id="0" width="796" height="796" class=" bs-1416663517803-1" viewBox="-0.5 -0.5 796 796">
  <defs></defs>
  <g data-bs-id="1087">
    <g data-bs-id="1089">
      <path data-bs-id="1088" d="M 0 0 l 100 0 l 0 100 l -100 0 Z" 
            fill="rgba(255,0,0,1)" 
            data-stroke="rgba(0,0,0,1)" 
            transform="matrix(1,0,0,1,10,10)" 
            stroke-width="0" 
            stroke-dashoffset="0"></path>
    </g>
  </g>
</svg>

which in turn renders like this:

img

These libraries allow you to work with SVG nodes, attributes, and values indirectly, via a higher-level abstraction.

Canvas libraries

Fabric.js, Paper.js, Kinetic.js, etc.

These use canvas as the underlying technology to render graphics. This is raster graphics. They are also both abstractions and "gateways" that allow you to execute something like this (example from Fabric):

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

and have it rendered like this:

img

Since these libraries are canvas-based, the document will only have <canvas> element. Everything else is represented internally with (lower-level) code like this:

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

Canvas libraries with SVG-parsing

Fabric.js, canvg, etc.

These are a subset of Canvas libraries, but with support of parsing SVG. This means a library can take SVG like this:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800" height="700" xml:space="preserve">
  <rect x="10" y="10" width="100" height="100" stroke="blue" fill="purple" fill-opacity="0.5" stroke-opacity="0.8"/>
</svg>

And render it like this:

img

This is essentially SVG -> canvas conversion. And it's also vector -> pseudo-raster conversion. The reason it's pseudo-raster is because there's no loss in quality (at least in case of Fabric). When transforming vector SVG, Fabric makes a virtual and non-raster object out of it, and that object can then be rendered in any size, angle, position, etc. without loss of quality. It can even be exported back to SVG. Only when rendered on canvas, then it becomes raster graphics.

WebGL libraries

Three.js, Babylon.js, c3DL, Pixi.js, etc.

These are a superset of Canvas libraries (based on <canvas>, not SVG) that use WebGL rendering context rather than "2d" context:

// webgl canvas libraries
canvas.getContext('webgl');

// non-webgl canvas libraries
canvas.getContext('2d');

WebGL canvas libraries use a completely different API for drawing graphics via canvas comparing to non-WebGL canvas libraries. They also often have support for "2d" context, as a fallback scenario.

WebGL 2d vs 3d

WebGL libraries can also be categorized into 2d and 3d — those "specializing" in 2d or 3d output. The most popular example of 3d webgl library is Three.js and 2d — Pixi.js.

As a side note, once we add support for WebGL renderer in Fabric.js, the library will go from "canvas library with SVG support" to "webgl-capable canvas library with SVG support" :)

like image 130
kangax Avatar answered Nov 08 '22 08:11

kangax