jangobrick / php-svg
Requires
- php: >=7.4.0
Requires (Dev)
- meyfa/phpunit-assert-gd: ^v3.0.0
- phpmd/phpmd: ^2.15.0
- phpunit/phpunit: ^9.6.16
- rector/rector: ^1.0
Suggests
- ext-gd: Needed to rasterize images
- ext-simplexml: Needed to read SVG strings and files
This package is auto-updated.
Last update: 2024-07-12 11:42:49 UTC
README
PHP应用的零依赖矢量图形库
特性
PHP-SVG可以帮助完成以下一系列任务:
- 使用PHP代码程序性地生成矢量图形。生成的SVG字符串可以写入文件或作为HTTP响应的一部分发送。
- 加载和解析SVG图像到易于修改和附加的文档树中。
- 将矢量图形转换为栅格图像格式,如PNG或JPEG(光栅化)。
请注意,PHP-SVG仍处于alpha阶段,可能不适合复杂的应用程序。欢迎贡献。 了解如何贡献。
安装
需求
PHP-SVG没有依赖。它只需要满足以下要求的PHP安装:
- PHP版本7.4或更高。此库针对所有版本进行了测试,包括并限于PHP 8.3。
- 如果您想加载SVG文件或包含SVG代码的字符串,您需要安装'simplexml' PHP扩展。
- 如果您想使用光栅化功能将SVG转换为栅格图像(PNG、JPEG等),您需要安装'gd' PHP扩展。
这些扩展几乎总是存在于典型的PHP安装中。但是,您可能想确认您的托管提供商确实拥有它们。如果缺少SimpleXML或GD,PHP-SVG仍然可以执行除了需要缺少的扩展的任务之外的所有任务。例如,程序性地生成SVG图像并以XML形式输出始终有效,即使没有任何扩展。
Composer(推荐)
此包可在Packagist上找到,可以使用Composer安装。
composer require meyfa/php-svg
这将向您的composer.json文件添加一个依赖项。如果您还没有,请通过在PHP脚本顶部添加以下require
语句来设置Composer依赖项的自动加载:
<?php require_once __DIR__ . '/vendor/autoload.php';
您可能需要根据脚本所在的文件夹路径进行调整。
手动安装
下载此存储库的最新版本或当前的开发版本,并在您的项目中某个位置解压缩源代码。然后您可以使用我们自己的自动加载器来使SVG命名空间可用
<?php require_once __DIR__ . '/<path_to_php_svg>/autoloader.php';
其余部分与Composer完全相同,只是没有包管理器的优势。
入门
本节包含一些简单的示例,以帮助您开始使用PHP-SVG。
程序性地创建SVG
以下代码生成一个包含蓝色正方形的SVG。然后它设置Content-Type头并将SVG作为文本发送给客户端
<?php require __DIR__ . '/vendor/autoload.php'; use SVG\SVG; use SVG\Nodes\Shapes\SVGRect; // image with dimensions 100x100 $image = new SVG(100, 100); $doc = $image->getDocument(); // blue 40x40 square at the origin $square = new SVGRect(0, 0, 40, 40); $square->setStyle('fill', '#0000FF'); $doc->addChild($square); header('Content-Type: image/svg+xml'); echo $image;
将SVG转换为字符串
上述示例使用echo
,它隐式地将SVG转换为包含其XML表示的字符串。这种转换也可以显式进行
// 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 class="svg-container">' . $xmlString . '</div>';
从字符串加载SVG
除了从头开始生成图像外,还可以从字符串或文件中解析它们。以下代码解析一个SVG字符串,修改图像的一部分,并将结果输出到客户端
<?php require __DIR__ . '/vendor/autoload.php'; use SVG\SVG; $svg = '<svg width="100" height="100">'; $svg .= '<rect width="40" height="40" fill="#00F" id="my-rect" />'; $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;
从文件加载SVG
如果要从文件而不是字符串加载,请调用SVG::fromFile($file)
。该函数支持本地文件系统上的路径以及远程URL。例如
// 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');
光栅化
⚠️ 特别指出,该功能仍在积极开发中。许多事情看起来可能不正确,渲染大图像可能非常慢。
使用toRasterImage($width, $height [, $background])
方法将SVG渲染为光栅图像。结果是GD图像资源。GD提供方法将此资源编码为多种格式
<?php require __DIR__ . '/vendor/autoload.php'; use SVG\SVG; use SVG\Nodes\Shapes\SVGCircle; $image = new SVG(100, 100); $doc = $image->getDocument(); // circle with radius 20 and green border, center at (50, 50) $doc->addChild( (new SVGCircle(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);
光栅图像将默认保留SVG中存在的任何透明度。对于需要不透明图像的情况,可以指定一个背景颜色。在输出到某些格式(如JPEG,无法编码alpha通道信息)时,这可能是必需的。例如
// white background $rasterImage = $image->toRasterImage(200, 200, '#FFFFFF'); imagejpeg($rasterImage, 'path/to/output.jpg');
文本渲染(加载字体)
PHP-SVG使用手工制作的TTF解析器实现了对TrueType字体(.ttf
文件)的支持。由于PHP没有内置任何字体文件,您需要提供自己的字体。以下示例显示了如何加载一组字体文件。PHP-SVG将尝试根据CSS规范中的算法为给定的文本元素选择最佳匹配的字体。
<?php require __DIR__ . '/vendor/autoload.php'; use SVG\SVG; // load a set of fonts from the "fonts" directory relative to the script directory SVG::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));
请注意,PHP在使用相对路径时经常表现异常,尤其是在字体方面。因此,建议使用绝对路径,或使用__DIR__
常量将当前脚本的目录作为前缀。
文档模型
本节将更详细地解释对象结构和如何查询或修改文档的某些部分。
SVG根节点
SVG
类的实例表示图像的抽象形式。它本身不存储DOM信息。这是文档根节点(对应于<svg>
XML标签的对象)的责任。例如
<?php require __DIR__ . '/vendor/autoload.php'; use SVG\SVG; $svg = '<svg width="100" height="100">'; $svg .= '<rect width="40" height="40" fill="#00F" id="my-rect" />'; $svg .= '</svg>'; $image = SVG::fromString($svg); // obtain the <svg> node (an instance of \SVG\SVGDocumentFragment): $doc = $image->getDocument();
子节点
任何元素的子节点可以通过以下方式获得
// 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');
根节点有一个额外的功能,可以通过其id
属性获取唯一元素
// Returns an element or null.
$element = $doc->getElementById('my-rect');
可以添加、删除和替换子节点
// 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);
属性
每个属性都可通过$element->getAttribute($name)
访问。一些常用属性有额外的快捷方法,但它们仅在有效的类中可用,所以请确保您访问的节点是正确的类型,以避免运行时错误。以下是一些示例
$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%');
样式
一些表现属性被SVG规范视为样式属性。这些将由PHP-SVG特别处理,并通过getStyle
和setStyle
而不是getAttribute
和setAttribute
提供。考虑以下节点
<circle x="10" y="10" r="5" style="fill: #red" stroke="blue" stroke-width="4" />
x
、y
和r
是属性。fill
、stroke
和stroke-width
是样式。
调试
如果您没有输出,只有空白页面,请尝试临时启用PHP的错误报告以找到问题的原因。
<?php error_reporting(E_ALL); ini_set('display_errors', 1); // ... rest of the script ...
完成操作后,请确保禁用此功能,因为它可能会泄露有关您的服务器设置敏感信息。另外,请确保在此模式下不要将Content-Type
头设置为图像格式,因为您的浏览器将尝试将错误消息作为图像渲染,这是不会工作的。
或者,您可能尝试找到您服务器的错误日志文件。它的位置取决于您如何运行PHP。
贡献
本项目免费向社区开放,但仍有许多工作要做。任何帮助都受欢迎!你可以以下方式贡献
- 在GitHub上给PHP-SVG加星标以传播消息。 使用得越多,它就会变得越好!
- 报告你遇到的任何错误或缺失功能。 请快速搜索问题标签,看看是否有人已经报告了相同的问题。也许你可以添加一些讨论内容?
- 通过贡献代码。 你可以查看目前开放的议题,了解需要做什么工作。如果你遇到了你知道如何解决的问题,直接提交修复作为pull request应该是相当安全的。对于新功能,建议首先为你提出的建议创建一个议题,以收集反馈并讨论实现策略。
请阅读
通过pull request或commit向PHP-SVG贡献材料或代码,你确认你拥有该材料或代码的必要权利,并同意在MIT许可的条款下提供该材料或代码。