SVG
is a specification of a drawing like a file format. A SVG is a document. You can exchange SVG files like HTML files. And additionally because SVG elements and HTML elements share the same the DOM API, it is possible to use JavaScript to generate a SVG DOM in the same way as it is possible to create a HTML DOM. But you do not need JavaScript to generate SVG file. A simple text editor is enough to write a SVG. But you need at least a calculator to calculate the coordinates of the shapes in the drawing.
CANVAS
is just a drawing area. It it necessary to use JavaScript to generate the contents of a canvas. You can not exchange a canvas. It is no document. And the elements of the canvas are not part of the DOM tree. You can not use the DOM API to manipulate the contents of a canvas. Instead you have to use a dedicated canvas API to draw shapes into the canvas.
The advantage of a SVG
is, that you can exchange the drawing as a document. The advantage of the CANVAS
is, that is has a less verbose JavaScript API to generate the contents.
Here is an example, which shows that you can achieve similar results, but the way how to do it in JavaScript is very different.
// Italic S in SVG
(function () {
const ns='http://www.w3.org/2000/svg';
let s = document.querySelector('svg');
let p = document.createElementNS (ns, 'path');
p.setAttribute ('id', 'arc');
p.setAttribute ('d', 'M 0.9 -0.9 a 0.8,0.4 -10 0,0 -0.9,0.9');
s.appendChild (p);
let u = document.createElementNS (ns, 'use');
u.setAttribute ('href', '#arc');
u.setAttribute ('transform', 'rotate(180)');
s.appendChild (u);
})();
// Italic S in CANVAS
(function () {
let c = document.querySelector('canvas');
let w = c.width = c.clientWidth;
let h = c.height = c.clientHeight;
let x = c.getContext('2d');
x.lineWidth = 0.05 * w;
x.moveTo (w/2, h/2);
x.bezierCurveTo (w*0.02, h*0.4,
w*0.4, -h*0.02,
w*0.95, h*0.05);
x.moveTo (w/2, h/2);
x.bezierCurveTo (w*(1-0.02), h*(1-0.4),
w*(1-0.4), h*(1+0.02),
w*(1-0.95), h*(1-0.05));
x.stroke();
})();
svg, canvas {
width: 3em;
height: 3em;
}
svg {
vertical-align: text-top;
stroke: black;
stroke-width: 0.1;
fill: none;
}
canvas {
vertical-align: text-bottom;
}
div {
float: left;
}
<div><svg viewBox="-1 -1 2 2"></svg>VG</div>
<div>CANVA<canvas></canvas></div>
As you can see the result is almost the same, but the JavaScript code is completely different.
SVG is created with the DOM API using createElement
, setAttribute
and appendChild
. All graphics are in the attribute strings. SVG has more powerful primitives. The CANVAS for example has nothing equivalent to the SVG arc path. The CANVAS example tries to emulate the SVG arc with a Bezier curve. In SVG you can reuse elements in order to transform them. In the CANVAS you can not reuse elements. Instead you have to write a JavaScript function in order to call it twice. SVG has a viewBox
which allows to use normalized coordinates, which simplifies rotations. In the CANVAS you have to calculate the coordinates yourself based of the clientWidth
and clientHeight
. And you can style all SVG elements with CSS. In the CANVAS you can not style anything with CSS. Because SVG is a DOM, you can assign event handlers to all SVG elements. The elements in the CANVAS have no DOM and no DOM event handlers.
But on the other hand the CANVAS code is much easier to read. You do not need to care about XML name spaces. And you can directly call the graphics functions, because you do not need to build a DOM.
The lesson is clear: if you quickly want to draw some graphics, use the CANVAS. If you need to share the graphics, like to style it with CSS or want to use DOM event handlers in your graphics, build an SVG.