APEX@IGP

Infogrid Pacific-The Science of Information

21

SVG Primitives. The Basic Tools

How IGP SVG Primitives are constructed and optimized for manual tagging, reuse and direct insertion into HTML5 documents. Modified: 20 December 2015

WARNING. If your browser does not support SVG you will not see much of interest on this page.

These pages are not an SVG hand tagging tutorial. There are many competent tutorials available online for that. If you are interested in grinding through the syntax and learning a trick or two, a good starting point is the SVG Tutorial at Mozilla or this SVG Tutorial by Jakob Jenkov. This SVG Tutorial by Matthew Bystedt is particularly useful with some nice tricks thrown in.

Do you want to learn how to make great handcrafted SVG?

Visit our new  Interactive SVG Tutorial Site here ►.

Hand-crafted SVG has many advantages over application created SVG. It is usually tidier, smaller and readable. But most importantly in a digital content setting, it is easy to reusable and modify.

What is important is a basic awareness of the major SVG elements and attributes, plus the core SVG syntax. This allows you to quickly insert, delete or modify the SVG Primitives.

There are some basic techniques available with SVG that it is helpful to know and be able to use freely.

The Shapes

Here are the main SVG shapes. These are reasonably relevant to drawings for maths and similar education content; geometry and trigonometry in particular.

Each of these shapes is a standard SVG Primitive that have been simply cut and pasted into one SVG. Then simple transforms have been applied to size and position them.

Click on the View the SVG button to see the source code.

polygon (as triangle) rect circle ellipsis line polyline {C}{C} polygon (as Hexagon)

View the SVG

    

The seven basic shapes are:

  1. Circle
  2. Ellipsis
  3. Polygon
  4. Rectangle
  5. Line
  6. Polyline
  7. Path

Most of these are easy to use. Path however does become very complex when used for arcs, and bezier curves. Because this is not an SVG tutorial, that's all the information on shapes and lines at this stage.

What is important for the reuse and extension of SVG Primitives is how they are constructed and packaged read to work.

SVG Primitive File Structure

To enable fast reuse, remixing, combination and layout and presentation control the SVG Primitives are organized with a number of component groups.

The grouping can be seen in this code example below. Also note that the defined CSS matches these groups.

<svg height="400" width="400">
    <defs>
      CSS and 
      markers (arrows) and
      symbols (tick marks and angles) go in here...
    </defs>
<!-- THE SHAPE Eg:SCALENE TRIANGLE -->
<polygon... The main shape defined. 
<!-- POINTS -->
... If a shape has points these are set here
<!-- TICK MARKS -->
... If a shape has tick marks these are set here
<!-- ANGLES -->
... If a shape has angle markers these are set here
<!-- TEXT VERTICES -->
...If a shape uses vertex lettering that is set here
<!-- TEXT LINES -->
...If a shape uses line lettering that is set here
<!-- LABEL -->
...If an SVG element has a label that is set here
<!-- CONSTRUCTION COMPONENTS -->
... If a shape has construction lines, circles, etc. These 
are set here. 

<defs>

This contains the items that are used in the whole file. In SVG Primitives that is CSS and markers. Markers are not included in the general primitives unless they are required.

The Shape

This is the basic defined shape with its layout metrics and any required transforms. This is at the bottom of the drawing stack.

All the primitives shapes are size matched and consistently positioned to the center of the standard drawing box.

Points

Where points are important (and some primitives will have only points) these are next. Generally they are aligned with the vertices of the shape when appropriate. If you don't want them, remark or delete them.

Tick Marks

When lines need tick-marks to show size equivalency these are applied. This is used extensively in basic triangles and quadragons.

Angles

These allow the positioning of angle markers for various degrees. The default set in SVG Primitives is 30deg, 45deg, 60deg, 90deg and 120deg. Any other special angle marker requirements will have to be hand-crafted.

Text Vertices/Lines.

Vertices and Lines are grouped separately because the coordinates are very different layouts. These can also be styled independently if required. They are organized starting from the top in an anti-clockwise direction.

Caption

If the drawing requires a caption or title this is maintained independently with a matching CSS style. It also allows for<tspan> to be applied for spot text emphasis.

Construction Components

These are the lines, circles, shapes and points that have been used to construct any specific SVG Primitive. These may be required in an instructional context so are made available. It also means anyone can extend the method to any other required shapes.

Generally you will delete construction components in most created files unless you are actually demonstrating construction methods in the drawing.

 

Further information on using the SVG Primitive bits is explained in the Using SVG Primitives article.

Styling

Generally in any particular book the line-art styles will be relatively consistent and can use the same style-set.

It is important to keep the size of any SVG structure to the smallest it can be. Use CSS to reduce the size and complexity of the files; and more particularly to make the noisy SVG elements less cluttered with attributes. 

When you combine a number of SVG elements together this enables you to focus on the position, units and any required transforms without having to fight with a large list of styles. This is a serious file-size advantage with hand-crafted SVG used inline in the HTML5 page.

You can change and customize the default styles at anytime. Remember these are SVG Primitives; that means a basic starter-kit.

Default SVG Primitives CSS

If used, this is inserted into the <defs> element at the top of the file.

<style type="text/css"><![CDATA[
  .shape { stroke:black; fill:rgba(0, 255, 0, 0.5); stroke-width:1;}
  .point {fill:red;}
  .text1 {font-family:Arial; font-size:24px; fill:black; font-weight:normal; text-anchor:middle;}
  .text2 {font-family:Arial; font-size:20px; fill:black; font-weight:normal; text-anchor:middle;}
  .label  {font-family:Arial; font-size:18px; font-style:italic; fill:black; font-weight:normal; text-anchor:left;}
  .emphasis {font-weight:bold;}
  .tick {stroke:black; stroke-width:1;}
  .angle {stroke:black; stroke-width:1;}
  .construction {stroke:black; stroke-width:1; stroke-dasharray:2, 2; fill:transparent;}
]]></style>

Note that SVG CSS uses the SVG terms in the CSS syntax.

Also be aware the style="" attribute beats the SVG native attributes. Don't mix and match unless you are experimenting and know what you are doing.

Markers

Markers are created and can then be attached to a line or polygon, start, vertex or end by ID reference to the marker. They are joined to a line tangentally so they will point nicely even if attached to a curve.

SVG Primitives has a standard set of markers that can be used anywhere there is a line. The following can have markers attached:

line, polyline, path, polygon

Marker Shapes

There is a core set of marker shapes that can be used pretty much anywhere on the drawings. These are generally in pairs or triplets:

  • Arrow-start / Arrow-end
  • Circle-start / Circle-end
  • Dot-start / Dot-end
  • Square-start / Square-end
  • Line-start / Line-end / Line-middle
  • Cross-start / Cross-end / Cross-middle

These can all be extended and modified to taste for specific books and/or drawings. Creating markers is a little bit tricky as they have their own behaviours.

Start-End and Middle markers are required to address how they join to the line they are decoration. Markers can make a line "longer" and that will have to be taken into account when using them.

SVG inside SVG

In most XML files the root element is only allowed to be used once (even HTML!). SVG allows SVG to be included as an internal component. Eg:

<svg>
    <svg>...</svg>
    <svg>...</svg>
</svg>

This is very useful as it allows the assembly of multiple drawings very easily, each as a self-contained entity that can easily be editing and changed. With a little thinking and use of the height, width and viewBox attributes simple things can be combined to create more complex things.

Unfortunately Webkit SVG doesn't support transforms on embedded <svg> elements. To make them work in all browsers just wrap the embedded <svg> in a <g> tag an apply the required transforms to the <g> element.

alt

Production Note on the Layout Graph

Webkit does not support repeating-linear-gradient but does have -webkit-repeating-linear-gradient that uses percentages only in this attribute. The result is you will see a set of blurred lines instead of a grid.

repeating-linear-gradient works reliably in Firefox and IE10. If you want to see/use this grid technique you will have to use a supporting browser right now.

Because the layout graphs are only normally present in the IGP:Writer authoring mode and not the final output images we haven't bothered with cross-browser adjustments. We just use the right tools for the job!

{C}{C} {C}{C}

Multiple SVGs in a Parent SVG

The purpose of this example is to demonstrate how the SVG Primitives can be easily cut and pasted together to make new illustrations for anything. Nothing has to be redrawn.

This is the standard 400px SVG with four 300px diameter SVG circles pasted inside. The important point is they are just the standard 400px X 400px SVG Primitives.

These have had a 50% transform applied to make them 200px each with the circles at 150px diameter. The translate attribute is used to position the files into each corner using the original SVG size values.

Of course the SVG Primitives can also be opened in an SVG editing application such as InkScape.

View the SVG

alt

Production Note

Webkit browsers do not support transforms applied to nested SVG elements. Therefore for cross-browser compatibility where required separate SVG files should be wrapped into <g> elements and the transforms applied to the <g> elements.

If you are using a Webkit browser the samples above will show just one Orange circle. The example below has the transform in the <g> element and will show correctly in IE, Firefox and Webkit.

Multiple SVGs in a Parent SVG Modified for Webkit

Each SVG component has been placed in a parent <g> element to allow transform size and position control.

View the SVG

 

      

<svg height="400" width="400">
<!--Circle one positioned top left -->
<svg x="0" y="0" height="400" width="400" 
    transform="scale(0.5)">
<circle cx="200" cy="200" r="150"
    fill="red" 
    stroke="blue" 
    stroke-width="2"  />
</svg>    
<!--Circle two positioned top right -->
<svg x="0" y="0" height="400" width="400" 
    transform="scale(0.5) 
    translate(400,0)">
<circle cx="200" cy="200" r="150"
    fill="red" 
    stroke="blue" 
    stroke-width="2" />
</svg>
<!--Circle three positioned bottom left -->
<svg x="0" y="0" height="400" width="400" 
    transform="scale(0.5) 
    translate(0,400)">
<circle cx="200" cy="200" r="150"
    fill="red" 
    stroke="blue" 
    stroke-width="2" />
</svg>
<!--Circle four positioned bottom right -->
<svg x="0" y="0" height="400" width="400" 
    transform="scale(0.5) 
    translate(400,400)">
<circle cx="200" cy="200" r="150"
    fill="red" 
    stroke="blue" 
    stroke-width="2"  />
</svg>
</svg>
<svg height="400" width="400">
<!-- COMPROMISE PACKAGING FOR WEBKIT -->
<g height="400" width="400" transform="scale(0.5)">
<!--Circle one positioned top left -->
<svg x="0" y="0" height="400" width="400">
<circle cx="200" cy="200" r="150"
    fill="red" 
    stroke="black" 
    stroke-width="4"  />
</svg>    
</g>
<g height="400" width="400" transform="scale(0.5) translate(400,0)">
<!--Circle two positioned top right -->
<svg x="0" y="0" height="400" width="400">
<circle cx="200" cy="200" r="150"
    fill="blue" 
    stroke="black" 
    stroke-width="4" />
</svg>
</g>
<g height="400" width="400" transform="scale(0.5) translate(0,400)">
<!--Circle three positioned bottom left -->
<svg x="0" y="0" height="400" width="400">
<circle cx="200" cy="200" r="150"
    fill="green" 
    stroke="black" 
    stroke-width="4" />
</svg>
</g>
<g height="400" width="400" transform="scale(0.5) translate(400,400)">
<!--Circle four positioned bottom right -->
<svg x="0" y="0" height="400" width="400">
<circle cx="200" cy="200" r="150"
    fill="orange" 
    stroke="black" 
    stroke-width="4"  />
</svg>
</svg>
<svg x="0" y="0" height="400" width="800">
<g transform="scale(0.5) translate(0,0)" >
<!-- POLYGON - TRIANGLE -->
<svg x="0" y="0" height="400" width="400">
<polygon points="200,50 350,300 50,300"
    fill="rgba(0, 255, 0, 0.5)"
    stroke="black"
    stroke-width="4"/>
      <text x="200" y="390"
        text-anchor="middle"
         font-family="Arial, Helvetica, sans-serif"
     font-weight="normal"
     font-size="36"
     fill="black" >polygon (as triangle)</text>
</svg>
</g>
<g   transform="scale(0.5) translate(400,0)" >
<!-- RECTANGLE -->
<svg x="0" y="0" height="400" width="400">
  <rect x="50" y="100" width="300" height="200"
        fill="rgba(255, 0, 0, 0.5)"
    stroke="black"
    stroke-width="4"/>
    <text x="200" y="390"
        text-anchor="middle"
         font-family="Arial, Helvetica, sans-serif"
     font-weight="normal"
     font-size="36"
     fill="black" >rect</text>
</svg>
</g>
<g transform="scale(0.5) translate(800,0)" >
<!-- CIRCLE -->
<svg x="0" y="0" height="400" width="400">
<circle cx="200" cy="200" r="150"
        fill="rgba(0, 0, 255, 0.5)"
    stroke="black"
    stroke-width="4"  />
<text x="200" y="390"
        text-anchor="middle"
         font-family="Arial, Helvetica, sans-serif"
     font-weight="normal"
     font-size="36"
     fill="black" >circle</text>    
  </svg>
 </g>
<g transform="scale(0.5) translate(1200,0)" >
<!-- ELLIPSIS -->
<svg  x="0" y="0" height="400" width="400">
<ellipse cx="200" cy="200" rx="190" ry="140"
    fill="rgba(255, 255, 0, 0.5)"
    stroke="black"
    stroke-width="4" />
        <text x="200" y="390"
        text-anchor="middle"
        font-family="Arial, Helvetica, sans-serif"
        font-weight="normal"
        font-size="36"
        fill="black" >ellipsis</text>
</svg>
</g>
<g transform="scale(0.5) translate(0,400)" >
<!-- LINE -->
<svg  x="0" y="0" height="400" width="400">      
<line x1="50" y1="100" x2="350" y2="100"
            stroke="black" stroke-width="4"  />
<line x1="50" y1="200" x2="350" y2="200"
            stroke="black" stroke-width="6"  />
<line x1="50" y1="300" x2="350" y2="300"
            stroke="black" stroke-width="8"  />
<text x="200" y="390"
        text-anchor="middle"
         font-family="Arial, Helvetica, sans-serif"
     font-weight="normal"
     font-size="36"
     fill="black" >line</text>
</svg>
</g>
<g transform="scale(0.5) translate(400,400)" >
<!-- POLYLINE -->
<svg  x="0" y="0" height="400" width="400">
<polyline
    points="50,50 350,50 350,350 50,350
    50,100 300,100 300,300 100,300
    100,150 250,150 250,250 150, 250"
     fill="none"
     stroke="black"
     stroke-width="4" />
<text x="200" y="390"
        text-anchor="middle"
         font-family="Arial, Helvetica, sans-serif"
     font-weight="normal"
     font-size="36"
     fill="black" >polyline</text>
</svg>
</g>
<g transform="scale(0.5) translate(800,400)" >
<!-- POLYGON - HEXAGON -->
<svg x="0" y="0" height="400" width="400">            
<polygon points="250,75  358,137.5 358,262.5 250,325 142,262.6 142,137.5"
    fill="rgba(0, 255, 255, 0.5)"
    stroke="black"
    stroke-width="4" />
<text x="200" y="390"
    text-anchor="middle"
    font-family="Arial, Helvetica, sans-serif"
    font-weight="normal"
    font-size="36"
    fill="black" >polygon (as Hexagon)</text>
</svg>
</g>
<g transform="scale(0.5) translate(1200,400)" >
<!-- PATH WITH ARC -->
<svg x="0" y="0" height="400" width="400" >            
<polygon points="450,75  558,137.5 558,262.5 450,325 342,262.6 342,137.5"
    fill="transparent"
    stroke="black"
    stroke-width="4" />
<text x="200" y="390"
        text-anchor="middle"
         font-family="Arial, Helvetica, sans-serif"
     font-weight="normal"
     font-size="36"
     fill="black" >path</text>
</svg>
</svg>
comments powered by Disqus