SVG

Scalable Vector Graphics (SVG) for short, is an XML based format that describes graphics. This format may seem complicated enough to be confused with a full blown programming language for 2D graphics, but in truth it is just a markup language. While SVG may seem new to some web developers, the specification was first developed back in 1999.

The main difference between a vector graphic and a raster graphic (in other words, a bitmap) is the way that the graphic is described. In a bitmap, each pixel is essentially represented by three or four numbers, representing the color of that individual pixel (RGB), along with a possible opacity level. Looking at it from a broader sense, a bitmap is nothing more than a grid of pixels. Vectors, on the other hand, are described by a series of mathematical functions that describe lines, shapes, and colors, instead of each individual point on the entire image. To put it in simple terms, vector graphics do a fantastic job of scaling its dimensions, as illustrated in the following screenshot:

SVG

If you zoom in or try to stretch a vector graph, it will always be as smooth as the original, since the shape is defined (and scaled) using the same mathematical functions (as exemplified on the image on the left). Raster graphics, on the other hand, are only defined by the same grid of pixels. Scaling that grid just means multiplying the dimensions of the grid, resulting in the blocky, pixelated image represented by the image on the right.

Now, the SVG standard does much more than simply define shapes, lines, paths, and colors. The specification also defines transformations and animations that can be applied to any single primitive, a group of primitives, or the entire SVG context. The specification also allows for SVG to be a very accessible format, meaning that it is possible to include text and other meta data right into the file, so that other applications can understand the file in other ways besides just the graphics. For example, search engines can crawl and index, not only your web pages, but also any SVG graphic.

Since SVG is text based (as opposed to storing binary data, such as an audio file, for example), it is also possible to compress an SVG image using such compression algorithms as the popular Gzip, which is so prevalent in the world of web development these days. When an SVG file is saved as its own, standalone file, it is given the extension .svg. If the file is Gzip compressed, that extension should be .svgz, so that the browser knows to uncompress the file before processing it.

SVG files can be used in an HTML file in a few different ways. Since the file itself can be saved as its own file, it is possible to embed the entire file on a page using the object tag, using an ordinary image tag, or even using an XHR object to fetch its contents from a server, and injected right into the HTML document. Alternatively, the contents of an SVG file can be manually copied into the host HTML file, so that its contents are imported inline.

To import an SVG graphic inline into an HTML document, we simply insert an svg tag, with all of its contents as children nodes of it. As of this writing, the XML namespace attribute is required, along with the version number, as shown in the following code:

<body>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    width="150"
    height="150">

    <circle
      cx="75"
      cy="75"
      r="50"
      stroke="black"
      stroke-width="2"
      fill="red"></circle></svg>
</body>

While this may seem easy enough for a simple red circle, once the image gets to be more complex, it gets a bit hard to manage all of it in one file. Thus, it may be more convenient to simply save all of the SVG files externally, then import them individually. This approach also lends itself much better to resource sharing and reuse, as we can import the same graphic in multiple files without having to copy the entire file every time.

<body>
  <object type="image/svg+xml" data="red-circle.svg"
    width="100" height="100">
  </object>

  <img src="red-circle.svg" width="100" height="100" />
</body>

One final note about SVG before we dive into some hands on examples, is that every node inside the parent svg tag (including that parent node) is managed by the browser. Thus, every one of these nodes can be styled through CSS. If that's not enough, every node inside an SVG graphic can have browser events registered to them, allowing us to interact with the graphic and all of its individual components the same way as most other DOM elements. This makes SVG a very dynamic, highly flexible graphics format.

If the SVG instance is inlined with the HTML, then we can simply get a direct reference to the parent svg node, or to any child node direct though JavaScript. Once we have that reference, we can act on the objects just like any other DOM elements. However, if the SVG is external to the HTML, we need to take one extra step and load in the actual SVG file into the JavaScript variable. Once this step is done, we can work with the SVG's subtree as though it is local to the file.

<body>
  <object type="image/svg+xml" data="red-circle.svg"
    width="100" height="100">
  </object>

  <script>
    var obj = document.querySelector("object");

    // Very important step! Before calling getSVGDocument, we must register
        // a callback to be fired once the SVG document is loaded.
    obj.onload = function(){
      init(obj.getSVGDocument());
    };

    function init(svg) {
      var circles = svg.getElementsByTagName("circle");

      // Register click handler on all circles
      for (var i = 0, len = circles.length; i < len; i++) {
        circles[i].addEventListener("click", doOnCircleClick);
      }

      // When a circle element is clicked, it adds a CSS class "blue"
            // to itself.
    function doOnCircleClick(event) {
      this.classList.add("blue");
    }
  }
  </script>
</body>

A few important details about the preceding code snippet that you should always remember are:

  • The imported SVG Document is treated as an external document (similar to an Iframe), meaning that any CSS outside of that document (such as the host document) is outside of its scope. Thus, if you want to apply a CSS class to an SVG node from a getSVGDocument() call, that CSS class must be defined within the same SVG file that was imported originally.
  • The CSS attributes for SVG are slightly different. For example, instead of defining a background color you would define a fill color. Basically, the same attributes that are used on the SVG elements themselves, are the same ones you'd use in a corresponding stylesheet declaration.
  • Any browser-specific CSS attributes can be applied to SVG nodes (for example, transition, cursor, etc.)

Thus, the preceding example is completed with the following .svg file as the corresponding red-circle.svg file, as used in the following code snippet:

<svg
  xmlns="http://www.w3.org/2000/svg"
  version="1.1"
  width="150"
  height="150">

<style type="text/css">
.blue {
  /* CSS Specific to SVG */
  fill: #0000ff;

  /* CSS Specific to the browser */
  cursor: pointer;
  -webkit-transition: fill 1.25s;
}
</style>
  <circle
    cx="75"
    cy="75"
    r="50"
    stroke="black"
    stroke-width="2"
    fill="red"></circle>
</svg>

How to use it

Although it is highly recommended that you use a professional vector editor software when composing complex SVG graphics, such as Inkspace or Adobe Illustrator, this section will walk you through the basics of SVG composition. This way you can draw basic shapes and graphs by hand, or at least be familiar with the fundamentals of SVG drawing.

Remember that whether you are importing your SVG graphics into your HTML through any of the methods described previously, drawing them inline, or even creating them dynamically through JavaScript, you will need to include the XML namespace to the root svg element. This is a common mistake made by newcomers to SVG, which may result in your graphics not showing up on the page.

The primitive shapes we can draw with SVG are rectangle, circle, ellipse, line, polyline, polygon, and path. Some of these primitives share attributes (such as width and height), while others have attributes that are unique to that shape (such as the radius of a circle). Everything you see in an SVG graphic is a result of these primitives used together in some combination.

Everything in SVG is drawn inside an SVG canvas, which is defined by the parent svg tag. This canvas is always rectangular, even though the shapes inside it can be of any shape that can be created by any of the primitives. Also, the canvas has its own coordinate system, which places the point origin at the top left corner of the canvas. The width and height of the canvas (determined by the parent svg tag) determines the dimensions of the drawing area, and all the (x, y) points reference inside the canvas (by all the child elements of svg) are relative to that point.

As a boilerplate for the following examples, we'll assume an external svg file, where we'll set the canvas size to 1000 x 1000 pixels, and draw away inside it. To view the final result of each example, you can use any one of the methods described in the previous section on how to load an SVG image into an HTML file. the following code snippet shows how the svg tag is defined:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
</svg>

Drawing a rectangle is as simple as it can get with SVG. Simply specify a width and height to a rect element, and that's it. Optionally, we can specify a stroke width and stroke color (where a stroke is the same thing as a border), along with a background color. Take a look at the following code:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <rect
    width="400"
    height="150" />
</svg>

By default, every shape is rendered at the origin (x = 0, y = 0), with no stroke (stroke-width = 0), and a background color (fill) set to all black (hexadecimal value of #000000, and RGB value of 0, 0, 0).

The circle is drawn with a circle tag by specifying at least three attributes, namely an x and y position (denoted by cx and cy), along with a radius value (denoted by the letter r). The center of the circle is placed at position (cx, cy), and the radius length does not take into account the width of the stroke, if one is present.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <circle
    cx="0"
    cy="0"
    r="300"
    fill="#ff3" />

  <circle
    cx="200"
    cy="200"
    r="100"
    fill="#a0a" />
</svg>

You will notice that by default, just like positioned DOM elements, every node has the same z-index. Thus, if two or more elements overlap, whatever element was drawn last (meaning that it is positioned farther from the parent than its sibling element) is rendered on top.

Ellipses are very similar to circles, with the only difference being that they have a radius for each direction (vertical and horizontal). Other than that minor detail, drawing an ellipse is the exact same as drawing a circle. Of course, we can simulate circles by drawing ellipses that have both radii of the same length.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <ellipse
    cx="400"
    cy="300"
    rx="300"
    ry="100"
    fill="#ff3" />

  <ellipse
    cx="230"
    cy="200"
    rx="75"
    ry="75"
    fill="#a0a" />
  <ellipse
    cx="560"
    cy="200"
    rx="75"
    ry="75"
    fill="#a0a" />
</svg>

With those basic shapes out of the way, we will now proceed to drawing more complex shapes. Instead of just following a few predefined points and lengths, we now get to choose exactly where each point goes in the shapes we'll be drawing. While this makes it slightly harder to draw shapes by hand, it also makes the possibilities much more extensive.

Drawing a line is both simple and fast. Simply specify two points within the SVG coordinate space, and you have a line. Each point is specified by an enumerated (x, y) pair.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <line
    x1="50"
    y1="50"
    x2="300"
    y2="500"
    stroke-width="50"
    stroke="#c00" />
</svg>

Next we'll cover the polyline, which is an extension of a regular line. The difference between a line and a polyline is that, as the name implies, a polyline is a collection of lines. While a regular line only takes in two coordinate points, a polyline takes two or more points, with a line connecting them in order. Also, if we specify a fill color for the polyline, the last point will be connected to the first, and the shape formed by that enclosed area will have the fill applied to it. Obviously, if no fill is specified, the polyline is rendered as a simple shape made out of nothing but straight lines.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <polyline
    points="50, 10, 100, 50, 30, 100, 175, 300, 250, 10, 10, 400"
    fill="#fff"
    stroke="#c00"
    stroke-width="10"/>
</svg>

The next shape we'll look at is the polygon. Scarily similar to a polyline, the polygon is drawn exactly in the same way as a polyline, but with two very important distinctions. First, a polygon must have at least three points. Secondly, a polygon is always a closed shape. This means that the last point and the first point of the sequence are physically connected, whereas in a polyline, that connection is only made by the fill, if one is assigned to the polyline:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
    <polygon
        points="50, 10, 100, 50, 30, 100, 175, 300, 250, 10, 10, 400"
        fill="#fff"
        stroke="#c00"
        stroke-width="10"/>
</svg>
How to use it

The polyline is shown on the left side of the preceding screenshot, while the shape on the right is a polygon that uses the exact same points to describe its position and orientation. The only difference between the two is that a polygon is forcefully closed. Of course, we can also simulate that behavior using a polyline by simply manually connecting the last point with the first.

SVG also allows us to draw very complex shapes with smooth curves, instead of the line-based shapes covered previously. To do so, we can use the path element, which might be a little complex at first, as it has several different attributes we can manipulate. One key feature of paths is that it allows us to either move the pointer to a location within the coordinate space, or to draw a line to a point.

All path attributes that describe the path are put inside the d attribute. These attributes are as follows:

  • M: move to
  • L: line to
  • H: horizontal line to
  • V: vertical line to
  • C: curve to
  • S: smooth curve to
  • Q: quadratic Bezier curve
  • T: smooth quadratic Bezier curve
  • A: elliptical arc
  • Z: close path

These attributes can be repeated as many times as needed, although it may be a good idea to break down the overall drawing into multiple smaller paths. Some reasons to separate a larger drawing into multiple paths are to make the figure more manageable, easier to troubleshoot, and easier to understand. The code for this is as follows:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <path
    d="M 100 100
    L 100 300
    M 250 100
    L 250 300
    M 400 100
    L 400 300"
    fill="transparent"
    stroke-width="45"
    stroke="#333" />
</svg>

Unless you practice and train yourself to look at path descriptions, it may be hard to just look at those codes and visualize the path. Take your time and look at each attribute individually. The preceding example first moves the pointer to point (100, 100), then a line is drawn from that point to another point (100, 300). This makes a vertical line from the last position where the pointer was, to the point specified by the line to attribute. Next, the cursor is changed from where it was to a new position (250, 100). Note that simply moving the cursor doesn't affect any previous drawing calls, nor does it do any drawing at that time. Finally, a second vertical line is drawn to point (250, 300). A third line is drawn at an equal distance from the first line. This can be seen in the following screenshot:

How to use it

Note that whatever values we define for fill, stroke, stroke width, and so on, are applied to the entire path. The solution to the problem of wanting different fill and stroke values is to create additional paths.

Drawing curves is still a bit more complicated. A curve requires three values, namely two control points, and the final point to which the line is drawn. To illustrate how control points work, observe the following example:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <path
    d="M 250 100
    L 250 300
    M 400 100
    L 400 300"
    fill="transparent"
    stroke-width="45"
    stroke="#333" />
  <path
    d="M 150 300
    C 200 500,
    450 500,
    500 300"

    fill="transparent"
    stroke-width="45"
    stroke="#333" />

  <circle
    cx="150"
    cy="300"
    r="8"
    fill="#c00" />
  <circle
    cx="200"
    cy="500"
    r="8"
    fill="#c00" />
  <line
    x1="150"
    y1="300"
    x2="200"
    y2="500"
    stroke-width="5"
    stroke="#c00" />

  <circle
    cx="450"
    cy="500"
    r="8"
    fill="#c00" />
  <circle
    cx="500"
    cy="300"
    r="8"
    fill="#c00" />
  <line
    x1="450"
    y1="500"
    x2="500"
    y2="300"
    stroke-width="5"
    stroke="#c00" />
</svg>

While executing the preceding code as shown in the following screenshot, we can see the relationship between control points and the curvature of a line:

How to use it

This is a cubic Bezier curve where the red lines show where the first and last curve points connect with the control points.

Drawing curves just the way you want is a rather complex problem to solve by hand. Different curve functions behave different from each other, so be sure to experiment with them all until you get a good feel for how they each work. Remember that although it is a good idea to have at least some understanding of how these curves and other drawing primitives work, it is highly recommended that you always use appropriate software to help you create your drawings. Ideally, we would use our creativity to create the drawing, and let the computer figure out how to represent that using SVG.

Note

The description attributes for paths can be specified using either a lowercase or an uppercase letter. The difference is that an uppercase letter means that the point is absolute, and a lowercase letter means that the point is relative. This concept of relative and absolute points is not quite the same as in HTML, where a relative offset means that the destination point is relative to its own original location, and an absolute point is one that's completely relative to the element's parent.

In SVG world, an absolute point is relative to the canvas' origin, and a relative point is relative to the last point defined. For example, if you move the pointer to location (10, 10), then do a relative move with values of 10 15, the pointer will end up, not at location (10, 15), but 10 units away from the x position, and 15 units away from the y position. The new position of the pointer would then be location (20, 25).

Finally, SVG is capable of rendering text to the screen. Imagine how time consuming it would be to render each letter by hand using lines and paths. Thankfully, the SVG API specifies a very simple interface for text rendering.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <text
    x="100"
    y="300"
    fill="#c00"
    stroke="#333"
    stroke-width="2"
    style="font-size: 175px">I Love HTML5!</text>
</svg>

Now, the SVG standard does much more than simply define shapes, lines, paths, and colors. The specification also defines groups of elements, whereby one may literally group a collection of nodes, so that they can possibly all be treated together as a single unit. There are also transformations, animations, gradients, and even photo filters, all of which can be applied to the simple primitives that are described previously. Take a look at the following code:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="1000">
  <rect
    x="500"
    y="500"
    width="900"
    height="600"
    fill="#c00"
    stroke="#333"
    stroke-width="2"
    transform="translate(800, 50)
      rotate(55, 0, 0)
      scale(0.25)">

    <animate
      dur="1.5s"
      attributeName="x"
      values="-50; 100; -50"
      repeatCount="indefinite" />

    <animate
      dur="1.5s"
      attributeName="height"
      values="50; 300; 50"
      repeatCount="indefinite" />
  </rect>
</svg>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.138.104