- Notifications
You must be signed in to change notification settings - Fork95
Vector graphics (SVG) library for PHP
License
meyfa/php-svg
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
The zero-dependency vector graphics library for PHP applications
PHP-SVG can help with the following set of tasks:
- Generating vector graphics programmatically with PHP code. The resulting SVG string can be written to a file or sentas part of the HTTP response.
- Loading and parsing SVG images into document trees that are easy to modify and append.
- Converting vector graphics into raster image formats, such as PNG or JPEG (rasterization).
Please note that PHP-SVG is still in its alpha stage and may not be suitable for complex applications, yet.Contributions are very welcome.Find out how to contribute.
PHP-SVG is free of dependencies. All it needs is a PHP installation satisfying the following requirements:
- PHP version 7.4 or newer. This library is tested against all versions up to (and including) PHP 8.4.
- If you wish to load SVG files, or strings containing SVG code, you need to have the'simplexml' PHP extension.
- If you wish to use the rasterization feature for converting SVGs to raster images (PNGs, JPEGs, ...), you need tohave the'gd' PHP extension.
These extensions are almost always available on typical PHP installations. Still, you might want to make sure that yourhosting provider actually has them. If SimpleXML or GD are missing, PHP-SVG can still perform all tasks except thosethat require the missing extension. For example, programmatically generating SVG images and outputting them as XML willalways work, even without any extension.
This package is available onPackagist and can be installed withComposer:
composer require meyfa/php-svg
This adds a dependency to your composer.json file. If you haven't already, setup autoloading for Composer dependenciesby adding the followingrequire
statement at the top of your PHP scripts:
<?phprequire_once__DIR__ .'/vendor/autoload.php';
You may need to adjust the path if your script is located in another folder.
Download thelatest release or the currentdevelopment version of this repository, and extract thesource code somewhere in your project. Then you can use our own autoloader to make available the SVG namespace:
<?phprequire_once__DIR__ .'/<path_to_php_svg>/autoloader.php';
The rest works exactly the same as with Composer, just without the benefits of a package manager.
This section contains a few simple examples to get you started with PHP-SVG.
The following code generates an SVG containing a blue square. It then sets the Content-Type header and sends the SVG astext to the client:
<?phprequire__DIR__ .'/vendor/autoload.php';useSVG\SVG;useSVG\Nodes\Shapes\SVGRect;// image with dimensions 100x100$image =newSVG(100,100);$doc =$image->getDocument();// blue 40x40 square at the origin$square =newSVGRect(0,0,40,40);$square->setStyle('fill','#0000FF');$doc->addChild($square);header('Content-Type: image/svg+xml');echo$image;
The above example usesecho
, which implicitly converts the SVG to a string containing its XML representation. Thisconversion can also be made explicitly:
// This will include the leading <?xml ...?> tag needed for standalone SVG files:$xmlString = $image->toXMLString();file_put_contents('my-image.svg', $xmlString);// This will omit the<?xml ...?> tag for outputting directly into HTML:$xmlString = $image->toXMLString(false);echo '<div>' . $xmlString . '</div>';
In addition to generating images programmatically from scratch, they can be parsed from strings or loaded from files.The following code parses an SVG string, mutates part of the image, and echoes the result to the client:
<?phprequire__DIR__ .'/vendor/autoload.php';useSVG\SVG;$svg ='<svg width="100" height="100">';$svg .='<rect width="40" height="40" fill="#00F" />';$svg .='</svg>';$image =SVG::fromString($svg);$rect =$image->getDocument()->getElementById('my-rect');$rect->setX(25)->setY(25);header('Content-Type: image/svg+xml');echo$image;
For loading from a file instead of a string, callSVG::fromFile($file)
. That function supports paths on the localfile system, as well as remote URLs. For example:
// load from the local file system:$image =SVG::fromFile('path/to/file.svg');// or from the web (worse performance due to HTTP request):$image =SVG::fromFile('https://upload.wikimedia.org/wikipedia/commons/8/8c/Even-odd_and_non-zero_winding_fill_rules.svg');
⚠️ This feature in particular is very much work-in-progress.Many things will look wrong and rendering large images may be very slow.
ThetoRasterImage($width, $height [, $background])
method is used to render an SVG to a raster image. The result isa GD image resource. GD then provides methods for encoding this resource to a number of formats:
<?phprequire__DIR__ .'/vendor/autoload.php';useSVG\SVG;useSVG\Nodes\Shapes\SVGCircle;$image =newSVG(100,100);$doc =$image->getDocument();// circle with radius 20 and green border, center at (50, 50)$doc->addChild( (newSVGCircle(50,50,20)) ->setStyle('fill','none') ->setStyle('stroke','#0F0') ->setStyle('stroke-width','2px'));// rasterize to a 200x200 image, i.e. the original SVG size scaled by 2.// the background will be transparent by default.$rasterImage =$image->toRasterImage(200,200);header('Content-Type: image/png');imagepng($rasterImage);
The raster image will default to preserving any transparency present in the SVG. For cases where an opaque image isdesired instead, it is possible to specify a background color. This may be mandatory when outputting to some formats,such as JPEG, that cannot encode alpha channel information. For example:
// white background$rasterImage =$image->toRasterImage(200,200,'#FFFFFF');imagejpeg($rasterImage,'path/to/output.jpg');
PHP-SVG implements support for TrueType fonts (.ttf
files) using a handcrafted TTF parser. Since PHP doesn't comewith any built-in font files, you will need to provide your own. The following example shows how to load a set of fontfiles. PHP-SVG will try to pick the best matching font for a given text element, based on algorithms from the CSS spec.
<?phprequire__DIR__ .'/vendor/autoload.php';useSVG\SVG;// load a set of fonts from the "fonts" directory relative to the script directorySVG::addFont(__DIR__ .'/fonts/Ubuntu-Regular.ttf');SVG::addFont(__DIR__ .'/fonts/Ubuntu-Bold.ttf');SVG::addFont(__DIR__ .'/fonts/Ubuntu-Italic.ttf');SVG::addFont(__DIR__ .'/fonts/Ubuntu-BoldItalic.ttf');$image =SVG::fromString('<svg width="220" height="220"> <rect x="0" y="0" width="100%" height="100%" fill="lightgray"/> <g font-size="15"> <text y="20">hello world</text> <text y="100" font-weight="bold">in bold!</text> <text y="120" font-style="italic">and italic!</text> <text y="140" font-weight="bold" font-style="italic">bold and italic</text> </g></svg>');header('Content-Type: image/png');imagepng($image->toRasterImage(220,220));
Note that PHP often behaves unexpectedly when using relative paths, especially with fonts. Hence, it is recommended touse absolute paths, or use the__DIR__
constant to prepend the directory of the current script.
This section explains a bit more about the object structure and how to query or mutate parts of documents.
An instance of theSVG
class represents the image abstractly. It does not store DOM information itself. That is theresponsibility of the document root node, which is the object corresponding to the<svg>
XML tag. For example:
<?phprequire__DIR__ .'/vendor/autoload.php';useSVG\SVG;$svg ='<svg width="100" height="100">';$svg .='<rect width="40" height="40" fill="#00F" />';$svg .='</svg>';$image =SVG::fromString($svg);// obtain the <svg> node (an instance of \SVG\SVGDocumentFragment):$doc =$image->getDocument();
Child nodes of any element can be obtained as follows:
// Returns the number of children.$numberOfChildren =$element->countChildren();// Returns a child element by its index.$firstChild =$element->getChild(0);// Returns an array of matching child elements.$childrenThatAreRects =$element->getElementsByTagName('rect');// Returns an array of matching child elements.$childrenWithClass =$element->getElementsByClassName('my-class-name');
The root node has an additional function for obtaining a unique element by itsid
attribute:
// Returns an element or null.$element = $doc->getElementById('my-rect');
Child nodes can be added, removed and replaced:
// Append a child at the end.$doc->addChild(new \SVG\Nodes\Shapes\SVGLine(0,0,10,10));// Insert a new child between the children at positions 0 and 1.$g =new \SVG\Nodes\Structures\SVGGroup();$doc->addChild($g,1);// Remove the second child. (equivalent to $doc->removeChild($g);)$doc->removeChild(1);// replace the first child with $g$doc->setChild(0,$g);
Every attribute is accessible via$element->getAttribute($name)
. Some often-used attributes have additional shortcutmethods, but they are only available on the classes for which they are valid, so make sure the node you are accessingis of the correct type to prevent runtime errors. Some examples:
$doc->getWidth();// equivalent to: $doc->getAttribute('width')$doc->setWidth('200px');// equivalent to: $doc->setAttribute('width', '200px');$rect->setRX('10%');// equivalent to: $rect->setAttribute('rx', '10%');
Some presentation attributes are considered style properties by the SVG spec. These will be treated specially byPHP-SVG and made available viagetStyle
andsetStyle
instead ofgetAttribute
andsetAttribute
.Consider the following node:
<circlex="10"y="10"r="5"style="fill: #red"stroke="blue"stroke-width="4" />
x
,y
andr
are attributes.fill
,stroke
andstroke-width
are styles.
If you aren't getting any output but only a blank page, try temporarily enabling PHP's error reporting to find the causeof the problem.
<?phperror_reporting(E_ALL);ini_set('display_errors',1);// ... rest of the script ...
Make sure you disable this again when you're done, as it may leak sensitive information about your server setup.Additionally, ensure you're not setting theContent-Type
header to an image format in this mode, as your browser willtry to render the error message as an image, which won't work.
Alternatively, you may attempt to find your server's error log file. Its location depends on how you're running PHP.
This project is available to the community for free, and there is still a lot of work to do.Every bit of help is welcome! You can contribute in the following ways:
- By giving PHP-SVG a star on GitHub to spread the word. The more it's used, the better it will become!
- By reporting any bugs or missing features you encounter. Please quickly search through theissues tab to see whether someone has already reported the same problem.Maybe you can add something to the discussion?
- By contributing code. You can take a look at the currently open issues to see what needs to be worked on.If you encounter a bug that you know how to resolve, it should be pretty safe to submit the fix as a pull requestdirectly. For new features, it is recommended to first create an issue for your proposal, to gather feedback anddiscuss implementation strategies.
Please read:
By contributing material or code to PHP-SVG via a pull request or commit, you confirm that you own the necessary rightsto that material or code, and agree to make available that material or code under the terms of the MIT license.
About
Vector graphics (SVG) library for PHP