webbingbrasil / filament-maps

为 Filament 提供地图组件。

v3.0.0-beta.2 2024-04-03 12:11 UTC

README

使用 Leaflet 渲染地图小部件。

  • 支持同一页面上多个地图
  • 内置操作:CenterMapActionZoomActionFullpageActionFullscreenAction
  • 直接在地图控制按钮上添加 Filament 操作
  • 支持多层。包含 DarkModeTile 层。
  • 支持标记聚合

注意 对于 Filament 2.x,请使用 2.x 分支

安装

composer require webbingbrasil/filament-maps

使用

创建一个小部件类,并扩展 Webbingbrasil\FilamentMaps\Widgets\MapWidget

use Webbingbrasil\FilamentMaps\Actions;
use Webbingbrasil\FilamentMaps\Marker;
use Webbingbrasil\FilamentMaps\Widgets\MapWidget;

class Map extends MapWidget
{
    protected int | string | array $columnSpan = 2;
    
    protected bool $hasBorder = false;

    public function getMarkers(): array
    {
        return [
            Marker::make('pos2')->lat(-15.7942)->lng(-47.8822)->popup('Hello Brasilia!'),
        ];
    }

    public function getActions(): array
    {
        return [
            Actions\ZoomAction::make(),
            Actions\CenterMapAction::make()->zoom(2),
        ];
    }
}

如果您使用 make:filament-widget 命令创建了一个新小部件,请记住删除与之一起创建的视图,否则地图将无法渲染。

地图配置

对于某些配置,可以使用属性

  • $mapOptions:包含 Leaflet 可用选项的数组。有关详细信息,请参阅 Leaflet 文档
  • $tileLayerUrl:字符串或包含瓦片层 URL 的数组。默认为 OpenStreetMap
  • $hasBorder:在地图周围显示边框。默认为 true
  • $rounded:在地图周围显示圆角边框。默认为 true
  • $height:地图的高度。默认为 400px
  • $heading:设置地图的航向。
  • $footer:设置地图的页脚。
  • $fullpage:以全页模式显示地图。默认为 false

但您也可以使用 setUp 方法以获得更多控制

public function setUp(): void
{
    $this
        ->tileLayerUrl(...)
        ->height(..)
        ->rounded(..)
        ->mapOptions(..)
        ->mapMarkers([
            ...
        ])
        ->fitBounds([
            [lat, lng],
            [lat, lng]
            ...
        ])
        ->actions([
            ..
        ]);
}

setUp 方法在组件的 mount 阶段被调用。有关更多信息,请参阅 livewire 生命周期钩子

全局配置

如果您想为地图小部件的所有实例设置默认配置,您可以在服务提供者中使用 configureUsing 方法

MyMap::configureUsing(function (ResellerMap $widget) {
    $widget->mapMarkers([
        Marker::make('id')
            ->lat(51.505)
            ->lng(-0.09)
            ->popup('I am a popup')
            ->tooltip('I am a tooltip'),
    ])
    ->tileLayerUrl('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')
    ->tileLayerOptions([
        'attribution' => 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
    ])
});

瓦片层

默认情况下,地图使用 OpenStreetMap 瓦片,但您可以使用 $tileLayerUrl 属性或 tileLayerUrl 方法将其更改为任何其他提供者。建议同时使用 tileLayerOptions 设置正确的归属。

多个瓦片层

您还可以使用多个瓦片层

protected string | array  $tileLayerUrl = [
    'OpenStreetMap' => 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    'OpenTopoMap' => 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'
];

protected array $tileLayerOptions = [
    'OpenStreetMap' => [
        'attribution' => 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
    ],
    'OpenTopoMap' => [
        'attribution' => 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors, SRTM | Map style © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)',
    ],
];

并且您可以使用操作来更改瓦片层

Actions\Action::make('mode')
                ->icon('filamentmapsicon-o-square-3-stack-3d')
                ->callback('setTileLayer(mode === "OpenStreetMap" ? "OpenTopoMap" : "OpenStreetMap")'),

深色模式

如果您想使用深色模式瓦片层,您可以使用 HasDarkModeTiles 特性。这个特性将自动设置两个瓦片层并监听 Filament dark-mode-toggled 事件。您可以使用 $lightModeTileLayerUrl$darkModeTileLayerUrl 属性更改默认瓦片层。

操作

您可以向地图小部件添加操作。操作是按钮,可以点击它来执行使用 JS 回调的操作。您可以创建自己的操作或使用包中提供的操作。

缩放操作

ZoomAction 操作将在地图上添加一个按钮,可以放大或缩小地图。您可以使用 zoom() 方法设置缩放级别。

use Webbingbrasil\FilamentMaps\Actions;
Actions\ZoomAction::make()->zoom(2), // Zoom in/out 2 levels

中心地图操作

此操作将使地图中心定位在特定位置。

use Webbingbrasil\FilamentMaps\Actions;

public function getActions(): array
{
    return [
        Actions\CenterMapAction::make()->centerTo([51.505, -0.09])->zoom(13),
    ];
}

您还可以将地图中心定位在用户位置

Actions\CenterMapAction::make()->centerOnUserPosition()->zoom(13)

注意:中心对用户位置功能仅在用户浏览器支持 Navigator.geolocation 时才可用。此外,用户必须位于安全上下文(HTTPS)中,并需要允许访问位置。

适应边界

您可以使用 fitBounds() 调整地图的缩放级别和中心,以显示给定的地理区域

Actions\CenterMapAction::make()->fitBounds([
   [lat, lng],
   [lat, lng],
])

您可以为 fitBounds() 传递多个点或使用 setUp() 中配置的初始边界

public function setUp(): void
{
    $this->fitBounds([
        [lat, lng],
        [lat, lng],
        ...
    ]);
}

public function getActions(): array
{
    return [
        CenterMapAction::make()->fitBounds($this->getFitBounds()),
    ];
}

全页或全屏操作

您可以在地图中添加一个按钮,以全页或全屏模式显示。

use Webbingbrasil\FilamentMaps\Actions;
Actions\FullpageAction::make()
Actions\FullscreenAction::make()

自定义操作

您可以使用 Webbingbrasil\FilamentMaps\Actions\Action 创建自己的操作。

例如,添加新标记的操作

use Webbingbrasil\FilamentMaps\Actions;

Actions\Action::make('form')
        ->icon('filamentmapsicon-o-arrows-pointing-in')
        ->form([
            Forms\Components\TextInput::make('name')
                ->label('Name')
                ->required(),
            Forms\Components\TextInput::make('lat')
                ->label('Latitude')
                ->required(),
            Forms\Components\TextInput::make('lng')
                ->label('Longitude')
                ->required(),
        ])
        ->action(function (array $data, self $livewire) {
            $livewire
                ->addMarker(
                    Marker::make(Str::camel($data['name']))
                        ->lat($data['lat'])
                        ->lng($data['lng'])
                        ->popup($data['name'])
                )
                ->centerTo(location: [$data['lat'], $data['lng']], zoom: 13)
        })

在这个例子中,我们使用 addMarker() 方法动态添加新标记,并使用 centerTo() 设置新的地图中心和缩放级别。

您可以使用以下方式操作标记数据

$liveWire->mapMarkers(array $markers); // update the markers
$livewire->addMarker(Marker $marker); // add a new marker
$livewire->removeMarker(string $id); // remove a marker
$livewire->updateMarker(string $id, Marker $marker); // update a marker

注意:标记需要有一个唯一名称。如果您尝试添加与现有标记名称相同的标记,则现有的标记将被替换。

使用 JS

如果您想使用自定义javascript来操作地图而不使用 Livewire,则此方法很有用。

Actions\Action::make('center')
    ->alpineClickHandler(<<<JS
        map.setView([0,0], 2)
    JS)

使用 map 属性在您的操作处理程序中访问 Leaflet 实例。

操作位置

您可以使用 position() 方法设置操作的位置

$this
    ->actions([
        Actions\CenterMapAction::make()->position('topright'),
    ])
}

操作图标

您可以使用 icon() 方法设置操作图标

Actions\Action::make()->icon('heroicon-o-home')

标记

您可以将标记添加到地图小部件中。标记是地图上的点,可以单击以打开信息弹出窗口或执行 JS 回调。

use Webbingbrasil\FilamentMaps\Marker;

$this
    ->mapMarkers([
        Marker::make('id')
            ->lat(51.505)
            ->lng(-0.09)
            ->popup('I am a popup'),
        Marker::make('id')
            ->lat(51.505)
            ->lng(-0.09)
            ->tooltip('I am a tooltip')
            ->callback(<<<JS
                alert('Hello World!');
            JS),
    ])
}

回调方法在标记渲染期间调用,必须返回在点击事件上执行的 JS。使用 map 在您的回调中访问 Leaflet 实例。

标记聚合

您可以使用 MarkerCluster 类将标记分组。如果您在地图上有很多标记,这很有用。

use Webbingbrasil\FilamentMaps\MarkerCluster;

$this
    ->mapMarkers([
        MarkerCluster::make([
            Marker::make('id')
                ->lat(51.505)
                ->lng(-0.09)
                ->popup('I am a popup'),
            Marker::make('id')
                ->lat(51.505)
                ->lng(-0.09)
                ->tooltip('I am a tooltip')
                ->callback(<<<JS
                    alert('Hello World!');
                JS),
        ]),
    ])
}

标记图标颜色

您可以使用 color() 方法设置标记图标的颜色

Marker::make('id')
    ->color(Marker::COLOR_RED)

请参阅 Marker::COLOR_* 常量以获取所有可用颜色。默认颜色是 Marker::COLOR_BLUE

标记自定义图标

您可以使用 icon() 方法为标记设置自定义图标

Marker::make('id')
    ->icon(
        string $iconUrl,
        string $shadowUrl,
        array $iconSize,
        array $iconAnchor,
        array $popupAnchor,
        array $shadowSize
    )

您可以从 leaflet-color-markers 获取额外的图标和相关的配置

显示标记详细信息

目前,标记没有与操作相同的功能,但使用 livewire 事件,您可以执行类似操作,例如

为您的标记添加回调

Marker::make('place')->callback('Livewire.emit("updateFooter", ' . $placeId . ')');

在地图小部件中注册事件监听器

protected $listeners = ['updateFooter' => 'showMarkerData'];

public function showMarkerData($placeId)
{
    $place = Place::find($placeId);
    $this->footer = view('marker-details', $place);
}

多边形线

您可以将多边形线添加到地图小部件中。多边形线是地图上在两个经纬度点之间绘制的线。如果您有多个多边形线,则每条多边形线必须具有唯一的名称。

public function getPolylines(): array
{
    return [
        Polyline::make('polyline')
        ->latlngs([
            [45.51, -122.68],
            [37.77, -122.43],
            [34.04, -118.2]
        ])->options(['color' => 'blue', 'weight' => 5])
        ->tooltip('I am a tooltip')
        ->popup('I am a popup'),
    ];
}

您可以使用 Leaflet 多边形线选项 中列出的选项

多边形线操作

您可以使用上述描述的操作来操作多边形线

Actions\Action::make('add line')
    ->tooltip('Add line')
    ->icon('filamentmapsicon-o-map-pin')
    ->form([
        Forms\Components\TextInput::make('name')
            ->label('Name')
            ->required(),
        Forms\Components\Section::make('Start')
            ->schema([
                Forms\Components\TextInput::make('lat1')
                    ->label('Latitude')
                    ->required(),
                Forms\Components\TextInput::make('lng1')
                    ->label('Longitude')
                    ->required(),
            ]),
        Forms\Components\Section::make('End')
            ->schema([
                Forms\Components\TextInput::make('lat2')
                    ->label('Latitude')
                    ->required(),
                Forms\Components\TextInput::make('lng2')
                    ->label('Longitude')
                    ->required(),
            ]),
    ])
    ->action(function (array $data, self $livewire) {
        $livewire
            ->addPolyline(
                Polyline::make(Str::camel($data['name']))
                    ->latlngs([
                        [$data['lat1'], $data['lng1']],
                        [$data['lat2'], $data['lng2']]
                    ])
            );
    })

在这个例子中,我们使用 addPolyline() 方法动态添加新多边形线。您还可以使用 removePolyline()updatePolyline() 方法。

$livewire->addPolyline(Polyline::make('polyline-name')->latlngs([...])->options([..]));
$livewire->removePolyline('polyline-name');
$livewire->updatePolyline(Polyline::make('polyline-name')->latlngs([...])->options([...]));

多边形

您可以将多边形添加到地图小部件中。多边形是地图上在两个经纬度点之间绘制的线。如果您有多个多边形,则每个多边形必须具有唯一的名称。

public function getPolylgones(): array
{
    return [
        Polygone::make('polygone')
        ->latlngs([
            [45.51, -122.68],
            [37.77, -122.43],
            [34.04, -118.2]
        ])->options(['color' => 'blue', 'weight' => 5])
        ->tooltip('I am a tooltip')
        ->popup('I am a popup'),
    ];
}

您可以使用 Leaflet 多边形选项 中列出的选项

多边形操作

$livewire->addPolygone(Polygone::make('polygone-name')->latlngs([...])->options([..]));
$livewire->removePolygone('polygone-name');
$livewire->updatePolygone(Polygone::make('polygone-name')->latlngs([...])->options([...]));

矩形

您可以将矩形添加到地图小部件中。如果您有多个矩形,则每个矩形都必须有一个唯一名称。

public function getRectangles(): array
{
    return [
            Rectangle::make('rectangle')
                ->bounds([
                    [54.559322, -5.767822],
                    [56.1210604, -3.021240]
                ])->tooltip('rectangle')
                ->options(['color' => 'red'])
    ];
}

您可以使用以下链接中列出的选项:Leaflet 矩形选项

矩形操作

$livewire->addRectangle(Polygone::make('rectangle-name')->bounds([...])->options([..]));
$livewire->removeRectangle('rectangle-name');
$livewire->updateRectangle(Polygone::make('rectangle-name')->bounds([...])->options([...]));

圆圈

您可以将圆圈添加到地图小部件中。如果您有多个圆圈,则每个圆圈都必须有一个唯一名称。

public function getCircles(): array
{
    return [
            Circle::make('circle')
                ->lat(-15.7942)
                ->lng(-47.8822)
                ->options(['radius' => 200000])
                ->popup('Hello Brasilia!')
                ->tooltip('test2'),
    ];
}

您可以使用以下链接中列出的选项:Leaflet 圆圈选项

矩形操作

$livewire->addCircle(Circle::make('circle-name')->lat(...)->lng(...)->options([..]));
$livewire->removeCircle('circle-name');
$livewire->updateCircle(Circle::make('circle-name')->lat(...)->lng(...)->options([...]));

图片

Header & Footer Compact Only Header Light Mode Dark Mode Modal Action

致谢