meyfa / php-svg
使用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-09-12 11:56:03 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许可的条款下提供该材料或代码。