Scalable Vector Graphics (SVG)
November 30, 2011
This post assumes you have some familiarity with PHP. If that is not the case, I'd
suggest looking at the php.net tutorial or the
w3schools tutorial. SVG is an XML based
format, so you may want to learn about XML at
w3schools.com. Most modern browsers can display SVG images without trouble. If you
are using a version of Internet Explorer prior to IE 9, you will not be able to view
SVG. Stop now and download Chrome or
Firefox!
Scalable Vector Graphics (SVG) are not
like the most common image formats (things like JPEG and GIF) which are Raster Graphics.
A raster image contains color information for each individual pixel, making for much
larger files. In contrast, SVG files contain only the structural information necessary
to recreate an image. For example, a simple circle could be described with only a few
words about its position, radius, and color. So one of the benefits of SVG is image
files are much smaller than the equivalent JPEG.
The name "Scalable Vector Graphic" implies another benefit: the ability to
scale or zoom in without changing the image. For instance, if you blow up a
JPEG image of a circle, the edges will become jagged. Anti-aliasing is an imperfect
strategy which works only if you aren't changing the size of an object too much. But a
circle in SVG is described only by its position and radius, so you can zoom in forever
and always see a sharp edge (limited only by the resolution of your computer screen or
printer).
SVG files can be created either with a simple text editor, or a graphical editor
such as Inkscape. This post will focus on
creating images in a text file using the primitive SVG commands. Full documentation
of the latest version of SVG can be found at
w3.org. Without further ado, let's get to an
example.
Example 1.0 -- Rings
Here's some code to get you started writing a "Hello World!" Scalable Vector Graphic.
It doesn't really spell out "Hello World!" (although SVG can contain text, that's not
very exciting). Creating the images above required only slightly more sophistication,
and some PHP, but I'll get to that.
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; GeSHi has a deprecated constructor in /home/margar21/public_html/geshi.php on line 259
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="850" height="850" xmlns="http://www.w3.org/2000/svg" version="1.1"> <!-- Definitions are for graphical objects that may be used multiple times. Examples of objects that are always referenced to a definition are: cursor, filter, linearGradient, marker, radialGradient, etc. --> <defs> <radialGradient id="mycircle" cx="50%" cy="50%" r="50%" fx="50%" fy="50%"> <stop offset="0%" stop-color="rgb(146,85,143)" stop-opacity="0.04" /> <stop offset="100%" stop-color="rgb(156,76,142)" stop-opacity="1" /> </radialGradient> </defs> <!-- Any graphics object can be rotated or translated. In this case, we rotate the ellipse by 67 degrees about the coordinate point (x=400, y=690). The <g></g> tag defines a group of objects. --> <g transform="rotate(67 400 690)"> <!-- (cx, cy) is the coordinate of the center of the ellipse (rx, ry) is the radius of the ellipse in the horizontal and vertical directions. #mycircle references the gradient defined above. --> <ellipse cx="400" cy="690" rx="120" ry="200" fill="url(#mycircle)" /> </g> </svg>
|
So that looks simple enough (maybe?), but I wanted to have loads of circles all
positioned randomly, and I didn't want to have to figure out a color scheme by hand.
This is where PHP comes in real handy. Here's the code that I developed to produce
the lovely images shown above:
Deprecated: Function create_function() is deprecated in /home/margar21/public_html/geshi.php on line 4716
<?php // This allows the browser to recognize the content and render it properly header('Content-Type: image/svg+xml'); // Writing text to the file requires 'echo' statements in php. // Remember to escape all of your quotation marks! echo "<?xml version=\"1.0\" standalone=\"no\"?> \n"; echo "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"> \n"; echo "<svg width=\"850\" height=\"850\" xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"> \n"; // CREATE DEFINITIONS echo "<defs> \n"; // number of circles $circles = 30; // get some random opacities for each ring $opi = rand(1,25) * 0.01; $opf = rand(1,25) * 0.04; // color scheme for($i=0; $i<$circles; $i++) { // each bubble is made up of four rings, each ring of a slightly // different color (the 60 can be changed if you want to deviate further // from the main theme.The abs( ... ) is there to make sure you're // always between 0 and 255. $ri = 255 - abs(255 - ($rr + rand(0,60))); $gi = 255 - abs(255 - ($gg + rand(0,60))); $bi = 255 - abs(255 - ($bb + rand(0,60))); $rf = 255 - abs(255 - ($rr + rand(0,60))); $gf = 255 - abs(255 - ($gg + rand(0,60))); $bf = 255 - abs(255 - ($bb + rand(0,60))); // the width of each ring is set by offset="xx%". cx and cy indicate the // center of the gradient. fx and fy change the focus point. echo "<radialGradient id=\"basecolor" . $i . "\" cx=\"50%\" cy=\"50%\" r=\"50%\" fx=\"50%\" fy=\"50%\"> \n"; echo " <stop offset=\"0%\" stop-color=\"rgb(" . $ri . "," . $gi . "," . $bi . ")\" stop-opacity=\"" . $opi . "\" /> \n"; echo " <stop offset=\"100%\" stop-color=\"rgb(" . $rf . "," . $gf . "," . $bf . ")\" stop-opacity=\"" . $opf . "\" /> \n"; echo "</radialGradient> \n"; } echo "</defs> \n"; // PLACE CIRCLES for ($i=0; $i<$circles; $i++) { // pick a random position and radius for the ellipses // rotate the ellipses randomly echo " <g transform=\"rotate(" . $rot . " " . $cx . " " . $cy . ")\"> "; echo " <ellipse cx=\"" . $cx . "\" cy=\"" . $cy . "\" rx=\"" . $rx . "\" ry=\"" . $ry . "\" fill=\"url(#basecolor" . $i . ")\" /> "; echo "</g> \n \n"; } echo "</svg>"
|
So that's only 74 lines of code (I never know whether to count comments as code?)
for a lovely little design. One thing I discovered in this process: having a single
color theme is far more aethetically pleasing than picking truly random colors. There's
a lesson in here that it's always a good idea to play around with what goes inside
and outside of your for
loops!
|