DrawSVG.py


5 Jul 2011 Code on Github

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.

Comments (4)

Alex on 10 Oct 2011, 8:58 a.m.

Thanks, Peter, for much informations about SVG which are not, in my opinion, well covered over Internet or not well explained as you did.

I didn't mean get involved with Python, but after this I wish to find time for that too.

All the best!

Peter on 11 Oct 2011, 12:40 a.m.

Thanks Alex, I'm glad you found my website useful. I've actually been meaning to write a full SVG tutorial for a while now, but haven't had the time. Maybe soon. I would definitely recommend getting involved with Python if you can.

Cosmo on 21 Jul 2013, 6:59 p.m.

Just browsing on the subject of SVG rotating objects and found your site and hence this. I'm the author of playSVG https://github.com/cosmo-guffa/play-svg which serves a similar purpose. However, it contains more abstractions for geometric objects, OO path representation, and the building of SVG elements. One advantage of your code is the inclusion of CSS styles, great idea ! I'm considering implementing this in my work so thanks for the inspiration. I would love to have someone knowledgeable like you take a look at my code and give feedback, but if you're not into reading others code, I can understand. Thanks for sharing :)

Amarjeet on 31 Dec 2019, 5:06 a.m.

Suppose I have a Svg image, I want to get all the coordinates of path. How can I achieve thise.