Introduction

I've written dozens of different Python programs that write SVGs of various types, so I thought it was about time I wrote a single generic module to make writing SVGs easy. Unsurprisingly, I'm not the only person to have had this idea, but rather than try to learn how to use someone else's module, I decided to write my one. It's more fun anyway.

If anyone else wants to use the module it's available to download on Github, where is also a wiki explaining how to use it. I also have a Javascript library that does a similar thing, only in the browser.

I plan to keep adding to the program and creating helper modules (such as one for drawing graphs), which is why it's on Github. The basics are already in place, and I think it's pretty straightforward to use. You do need to know how SVG works - I have a tutorial if you don't. Below is a quick guide on how to use my SVG-writer.

Basics

To create an SVG:

from DrawSVG import SVG
mySVG = SVG()

To write the SVG to file:

mySVG.write('test.svg')

Creating elements

Elements are created, with the element type as the first argument, a dictionary of attributes as an optional second element, and a child as an optional third element:

mySVG.addChildElement('rect', {'x':20, 'y':40, 'width':80, 'height':50, 'fill': 'blue'})
mySVG.addChildElement('text', {'x':22, 'y':12,}, "Test text")

Which creates an SVG like this:

<svg version="1.1"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 xmlns="http://www.w3.org/2000/svg">
  <rect y="20" x="20" height="20" fill="blue" width="60"/>
  <text y="12" x="22">Test text</text>
</svg>

Which looks like this:

Test text

Note that there is nothing (yet) in the code to check that elements are valid or have the required attributes. Also, attributes appear in a random order because they're kept in a dictionary. The reason I pass a dictionary rather than generate one with **kwargs is that often the attribute names will be hyphenated (e.g. 'stroke-width'), which Python doesn't like outside of a string.

Editing elements

This is one area I want to improve in future. For now, when you create an element, it is returned, which allows you to bind it to a variable (which could be put in a dictionary of elements if you want to refer to them later. For example, you could replace the code that creates a text element with this:

text_element = mySVG.addChildElement('text')
text_element.attributes['x'] = 22
text_element.attributes['y'] = 12
text_element.addChildElement('Test text')

This is useful for creating nested elements:

g = mySVG.addChildElement('g', {'fill':'blue'})
g.addChildElement('rect', {'x':20, 'y':20, 'width':60, 'height':20})
g.addChildElement('text', {'x':22, 'y':12,}, "Test text")

Another point to note (one I'm pretty pleased with): SVG inherits from the SVG_Element class so can be treated in the same way. For example, you can define the attributes of the SVG when it's created:

mySVG = SVG({'width':200, 'height':100})

Or later:

mySVG.attributes['viewBox'] = '0 0 100 100'

CSS

One difference between the SVG and other SVG elements is that it can be contain a style element that creates CSS. When adding a style, the first argument is the CSS selector and the following is a dictionary of attribute: value. For example:

mySVG.addStyle('rect', {'fill': 'blue'})
mySVG.addStyle('.my-text', {'font-size': 12, 'font-family': 'Arial,sans-serif'})

This will create a style element like this:

<style> 
  .my-text{
    font-size: 12;
    font-family: Arial,sans-serif;
  }
  rect{
    fill: blue;
  }
</style>

There are still a few issues to sort out, and many ways to improve it, but even as it stands, I find it quite useful.