prinsfrank/php-geo-svg

生成Geo SVG

v0.0.2 2021-11-07 20:23 UTC

This package is auto-updated.

Last update: 2024-09-11 23:23:51 UTC


README

Banner

PHP Geo SVG

GitHub Build Status Scrutinizer Code Quality Code Coverage PHP Version Support

无需外部服务或牺牲隐私即可生成和显示地图。

为什么使用这个包?

在寻找高质量SVG文件用于我的博客,我发现所有SVG文件要么质量太低,要么被生成工具中的不必要元素污染严重,或者投影方式不正确。这个包提供了手动生成地图或从geojson文件生成地图的灵活性,这些文件更易于获取。

特性

  • 支持从GeoJSON(直接从文件、作为JSON字符串或从数组)创建SVG以及手动GeometryCollection。
  • 根据请求直接输出svg到您的用户或输出到文件。
  • 使用边界框绘制整个世界地图或其一部分。
  • 易于支持的投影。目前支持:等矩形、墨卡托、米勒和几个等面积投影(Lambert、Behrmann、Smyth、Trystan、Hobo-Dyer、Gall-Peters、Balthasart和Tobler的方形世界地图)。请提交PR添加更多。
  • 在创建或编辑GeometryCollection时,提供了一个Fluent接口,允许进行方法链式调用。

目录

设置

请确保您正在运行PHP 8.0或更高版本以使用此包

要立即开始,请在您的composer项目中运行以下命令;

composer require prinsfrank/php-geo-svg

或者仅用于开发;

composer require prinsfrank/php-geo-svg --dev

基础知识;创建SVG

假设我们想创建以下简单的洲际地图

Simplified continents map

我们可以使用多种方法在svg中使用此包创建此地图;

从GeoJSON文件

要从GeoJSON文件创建SVG,通过在GeometryCollectionFactory上调用createFromGeoJSONFilePath方法创建一个新的'GeometryCollection',如下所示;

显示代码

使用变量

$geoSVG = new GeoSVG();
$geometryCollection = GeometryCollectionFactory::createFromGeoJSONFilePath('/path/to/file.geojson');
$geoSVG->toFile($geometryCollection, 'output/file.svg');

Fluent

(new GeoSVG())
    ->toFile(
        GeometryCollectionFactory::createFromGeoJSONFilePath(__DIR__ . '/path/to/file.geojson'),
        'output/file.svg'
    );

从GeoJSON字符串

要从GeoJSON字符串创建SVG,通过在GeometryCollectionFactory上调用createFromGeoJsonString方法创建一个新的'GeometryCollection',如下所示;

显示代码

使用变量

$geoJsonString = '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-177,74],[-80,9],[-25,82]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-80,9],[-37,-7],[-70,-55]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-12,36],[30,37],[27,70],[-24,66]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-12,36],[30,37],[51,11],[22,-35],[-17,17]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[27,70],[30,37],[51,11],[131,-2],[171,67]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[115,-15],[153,-15],[148,-43],[114,-35]]]}}]}';


$geoSVG = new GeoSVG();
$geometryCollection = GeometryCollectionFactory::createFromGeoJsonString($geoJsonString);
$geoSVG->toFile($geometryCollection, 'output/file.svg');

Fluent

$geoJsonString = '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-177,74],[-80,9],[-25,82]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-80,9],[-37,-7],[-70,-55]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-12,36],[30,37],[27,70],[-24,66]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[-12,36],[30,37],[51,11],[22,-35],[-17,17]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[27,70],[30,37],[51,11],[131,-2],[171,67]]]}},{"type":"Feature","properties":{"featurecla":"Continent"},"geometry":{"type":"MultiLineString","coordinates":[[[115,-15],[153,-15],[148,-43],[114,-35]]]}}]}';

(new GeoSVG())
    ->toFile(
        GeometryCollectionFactory::createFromGeoJsonString($geoJsonString),
        'output/file.svg'
    );

从GeoJSON数组

要从GeoJSON数组创建SVG,通过在GeometryCollectionFactory上调用createFromGeoJSONArray方法创建一个新的'GeometryCollection',如下所示;

显示代码

使用变量

$geoJsonArray = ['type'=>'FeatureCollection','features'=>[['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-177,74],[-80,9],[-25,82]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-80,9],[-37,-7],[-70,-55]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-12,36],[30,37],[27,70],[-24,66]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-12,36],[30,37],[51,11],[22,-35],[-17,17]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[27,70],[30,37],[51,11],[131,-2],[171,67]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[115,-15],[153,-15],[148,-43],[114,-35]]]]]]];


$geoSVG = new GeoSVG();
$geometryCollection = GeometryCollectionFactory::createFromGeoJsonArray($geoJsonArray);
$geoSVG->toFile($geometryCollection, 'output/file.svg');

Fluent

$geoJsonArray = ['type'=>'FeatureCollection','features'=>[['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-177,74],[-80,9],[-25,82]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-80,9],[-37,-7],[-70,-55]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-12,36],[30,37],[27,70],[-24,66]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[-12,36],[30,37],[51,11],[22,-35],[-17,17]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[27,70],[30,37],[51,11],[131,-2],[171,67]]]]],['type'=>'Feature','properties'=>['featurecla'=>'Continent'],'geometry'=>['type'=>'MultiLineString','coordinates'=>[[[115,-15],[153,-15],[148,-43],[114,-35]]]]]]];

(new GeoSVG())
    ->toFile(
        GeometryCollectionFactory::createFromGeoJsonArray($geoJsonArray),
        'output/file.svg'
    );

从构建自己的GeometryCollection

要从GeometryCollection手动构建SVG,创建对象并添加任何您想要的几何形状

显示代码

使用变量

$geoSVG = new GeoSVG();
$geometryCollection = new GeometryCollection();

$continents = new MultiPolygon();
$geometryCollection->addGeometryObject($continents);

$outerBorderNorthAmerica = new LineString();
$outerBorderNorthAmerica->addPosition(new Position(-177, 74));
$outerBorderNorthAmerica->addPosition(new Position(-80, 9));
$outerBorderNorthAmerica->addPosition(new Position(-25, 82));
$outerBorderNorthAmerica->setFeatureClass('Continent');
$outerBorderNorthAmerica->setTitle('North America');
$polygonNorthAmerica = new Polygon($outerBorderNorthAmerica);
$continents->addPolygon($polygonNorthAmerica);


$outerBorderSouthAmerica = new LineString();
$outerBorderSouthAmerica->addPosition(new Position(-80, 9));
$outerBorderSouthAmerica->addPosition(new Position(-37, -7));
$outerBorderSouthAmerica->addPosition(new Position(-70, -55));
$outerBorderSouthAmerica->setFeatureClass('Continent');
$outerBorderSouthAmerica->setTitle('South America');
$polygonSouthAmerica = new Polygon($outerBorderSouthAmerica);
$continents->addPolygon($polygonSouthAmerica);

$outerBorderEurope = new LineString();
$outerBorderEurope->addPosition(new Position(-12, 36));
$outerBorderEurope->addPosition(new Position(30, 37));
$outerBorderEurope->addPosition(new Position(27, 70));
$outerBorderEurope->addPosition(new Position(-24, 66));
$outerBorderEurope->setFeatureClass('Continent');
$outerBorderEurope->setTitle('Europe');
$polygonEurope = new Polygon($outerBorderEurope);
$continents->addPolygon($polygonEurope);

$outerBorderAfrica = new LineString();
$outerBorderAfrica->addPosition(new Position(-12, 36));
$outerBorderAfrica->addPosition(new Position(30, 37));
$outerBorderAfrica->addPosition(new Position(51, 11));
$outerBorderAfrica->addPosition(new Position(22, -35));
$outerBorderAfrica->addPosition(new Position(-17, 17));
$outerBorderAfrica->setFeatureClass('Continent');
$outerBorderAfrica->setTitle('Africa');
$polygonAfrica = new Polygon($outerBorderAfrica);
$continents->addPolygon($polygonAfrica);

$outerBorderAsia = new LineString();
$outerBorderAsia->addPosition(new Position(27, 70));
$outerBorderAsia->addPosition(new Position(30, 37));
$outerBorderAsia->addPosition(new Position(51, 11));
$outerBorderAsia->addPosition(new Position(131, -2));
$outerBorderAsia->addPosition(new Position(171, 67));
$outerBorderAsia->setFeatureClass('Continent');
$outerBorderAsia->setTitle('Asia');
$polygonAsia = new Polygon($outerBorderAsia);
$continents->addPolygon($polygonAsia);

$outerBorderAustralia = new LineString();
$outerBorderAustralia->addPosition(new Position(115, -15));
$outerBorderAustralia->addPosition(new Position(153, -15));
$outerBorderAustralia->addPosition(new Position(148, -43));
$outerBorderAustralia->addPosition(new Position(114, -35));
$outerBorderAustralia->setFeatureClass('Continent');
$outerBorderAustralia->setTitle('Australia');
$polygonAustralia = new Polygon($outerBorderAustralia);
$continents->addPolygon($polygonAustralia);

$geoSVG->toFile($geometryCollection, 'output/file.svg');

Fluent

(new GeoSVG())
    ->toFile(
        (new GeometryCollection())
            ->addGeometryObject(
                (new MultiPolygon())
                    ->addPolygon(
                        new Polygon(
                            (new LineString())
                                ->addPosition(new Position(-177, 74))
                                ->addPosition(new Position(-80, 9))
                                ->addPosition(new Position(-25, 82))
                                ->setFeatureClass('Continent')
                                ->setTitle('North America')
                        )
                    )
                    ->addPolygon(
                        new Polygon(
                            (new LineString())
                                ->addPosition(new Position(-80, 9))
                                ->addPosition(new Position(-37, -7))
                                ->addPosition(new Position(-70, -55))
                                ->setFeatureClass('Continent')
                                ->setTitle('South America')
                        )
                    )
                    ->addPolygon(
                        new Polygon(
                            (new LineString())
                                ->addPosition(new Position(-12, 36))
                                ->addPosition(new Position(30, 37))
                                ->addPosition(new Position(27, 70))
                                ->addPosition(new Position(-24, 66))
                                ->setFeatureClass('Continent')
                                ->setTitle('Europe')
                        )
                    )
                    ->addPolygon(
                        new Polygon(
                            (new LineString())
                                ->addPosition(new Position(-12, 36))
                                ->addPosition(new Position(30, 37))
                                ->addPosition(new Position(51, 11))
                                ->addPosition(new Position(22, -35))
                                ->addPosition(new Position(-17, 17))
                                ->setFeatureClass('Continent')
                                ->setTitle('Africa')
                        )
                    )
                    ->addPolygon(
                        new Polygon(
                            (new LineString())
                                ->addPosition(new Position(27, 70))
                                ->addPosition(new Position(30, 37))
                                ->addPosition(new Position(51, 11))
                                ->addPosition(new Position(131, -2))
                                ->addPosition(new Position(171, 67))
                                ->setFeatureClass('Continent')
                                ->setTitle('Asia')
                        )
                    )
                    ->addPolygon(
                        new Polygon(
                            (new LineString())
                                ->addPosition(new Position(115, -15))
                                ->addPosition(new Position(153, -15))
                                ->addPosition(new Position(148, -43))
                                ->addPosition(new Position(114, -35))
                                ->setFeatureClass('Continent')
                                ->setTitle('Australia')
                        )
                    )
            ),
        'output/file.svg'
    );

不同的地球到平面的变换;投影

如果您想使用除默认等矩形以外的其他投影,可以!目前支持以下投影,但请随意添加并提交PR;

  • 等矩形
  • 墨卡托
  • 米勒

要指定要使用的投影,您可以使用构造函数;

$geoSVG = new GeoSVG(new MercatorProjection);

或使用'setProjection'方法;

$geoSVG = new GeoSVG();
$geoSVG->setProjection(new MercatorProjection);

仅显示世界的一部分;使用边界框

如果您想使用边界框,您必须知道要显示的最南西和最东北坐标,并为两者创建'BoundingBoxPositions'。将这些传递给边界框对象,您就有了一个边界框;

$northEastern = new BoundingBoxPosition(7.2, 53.5);
$southWestern = new BoundingBoxPosition(3.5, 50.8);

$boundingBox  = new BoundingBox($southWestern, $northEastern);

实际上使用它,可以将边界框传递给构造函数,位于投影之后;

$geoSVG = new GeoSVG($projection, $boundingBox);

或使用'setBoundingBox'方法设置边界框;

$geoSVG = new GeoSVG();
$geoSVG->setBoundingBox($boundingBox);