2013
09.15

Last week, my boss asked me to print some graphics we make trough the amazing d3js library.

The problem is that when printing directly from the browser the results are unpredictable. Things get out of place, and all the hard work is flushed down the toilet.

What is the best method to print something, PDF, using the amazing FPDF Library, but a new problem surfaced, how am I going to write an SVG to an PDF document using SVG?

Google is your friend, and I found an extension to FPDF to add SVG’s to a PDF, and found this class svg2pdf, made by Rhodopsin.

I didn’t even tested it, I’m sure that the class work perfectly fine, but I wanted something not so messy and complicated, and with several things that could go wrong, I decided to go another way, find a library that would convert an svg string to an image, png, jpg, doesn’t really matter, preferably png, but it’s not mandatory.

I tried Imagik, but to no avail, couldn’t manage to put Imagik to work with svg <-> png conversion.

Then I found rsvg, a command line utility, installed it on a server, and the first test worked perfectly. There are still some things to test, specially the image tab and the text tag.

But now I need something to write SVG, sure I could do every SVG by hand, but that would be cumbersome, and I didn’t had the patience.

And so the SVGCreator library is born ( gotta start working on these names right? ), highly inspired by d3js library.

It’s a very simple library, go on github for the source, it has chaining methods and it’s composer ready.

A simple example taken from the examples folder:

$attributesSvg = array(
			'width' => 1000,
			'height' => 1000
		  );

$svg = new \SVGCreator\Elements\Svg($attributesSvg);

$svg->append(\SVGCreator\Element::LINE)
	->attr('x1', 100)
	->attr('y1', 100)
	->attr('x2', 325)
	->attr('y2', 250)
	->attr('stroke', 'blue');

$circle = new \SVGCreator\Elements\Circle();

$circle->attr('cx', 250)
	->attr('cy', 140)
	->attr('fill', 'green')
	->attr('r', 20)
	->attr('stroke', 'cyan')
	->attr('stroke-width', '5px');

$svg->append($circle);

echo $svg->getString();

I think the code is pretty self explaining, but let’s go over a few things.

All the elements can be created by calling the constructor of the respective class, and we can pass an array as argument with the attributes we want for that element, or we can add them later, so the circle could be added like this:

</pre>
$attributes = array(
 'cx' => 250
 'cy' => 140
 'fill' => 'green'
 'r' => 20
 'stroke' => 'cyan'
 'stroke-width' => '5px'
 );
$circle = new \SVGCreator\Elements\Circle($attributes);
$svg->append($circle);
<pre>

And the result would be exactly the same.

This class has some validation, but not much, since we can put almost any attribute inside the svg tags, and by this I mean, I only validate some attributes when we are writting the SVG, for example the circle validates 3 attributes, cx, cy, and r, this are the mandatory attributes for the circle, for the line is x1, y1, x2, y2. And the validation is only if the attribute is >= 0. Doens’t validate anything else.

The validation of the several elements is the following:

  • circle ( cx, cy, r )
  • rect (width, height, x, y )
  • line ( x1, y1, x2, y2 )
  • svg ( width, height )

When one of this attributes is wrong or doesn’t exist, an Exception of type \SVGCreator\SVGException is throwed.

What is missing, unit testing, don’t really know how to do this, since it’s the first time, working with such a thing.

More tags, the image tag and text tag, maybe today, maybe tomorrow, I don’t know.

Complex figures, wouldn’t be nice, to simply call a class that accepts the x, y, radius and the number of points, and from there we could draw a pentagon or an hexagon? That would be nice, I’ve got to read some geometry books to find how to do this.

And you can also save it to disk, by calling:

$svg->saveElementAsFile('svgfile.svg');

Hope you like it.

PS: Added PHPDocs generation while writing this post…