doode/filament-map-picker

使用地理信息模块扩展地图绘制工具的基于地图的用户界面,轻松选择和检索地理坐标。

v1.1.1 2024-09-23 13:58 UTC

This package is auto-updated.

Last update: 2024-09-25 08:32:44 UTC


README

Latest Version on Packagist Total Downloads Software License

img_1.png

介绍

地图选择器是Filament的一个自定义字段,旨在简化在地图上选择位置并获取其地理坐标的过程,同时通过在地图中嵌入Geoman插件来提供便利。

  • 功能包括
    • Filament-v3的OpenStreetMap集成字段
    • 在标记移动完成后实时接收坐标
    • 根据您的喜好定制控件和标记外观
  • PHP和Filament的最新版本
  • 应用最佳实践

支持的地图

地图选择器目前支持以下地图

  1. Open Street Map (OSM)

根据需要和测试,将添加其他地图选项到软件包中。

安装

您可以通过Composer轻松安装此软件包

composer require doode/filament-map-picker

基本用法

资源文件

<?php
namespace App\Filament\Resources;
use Filament\Resources\Resource;
use Filament\Resources\Forms\Form;
use Doode\MapPicker\Fields\Map;
...

class FilamentResource extends Resource
{
    ...
    public static function form(Form $form)
    {
        return $form->schema([
            Map::make('location')
                ->label('Location')
                ->columnSpanFull()
                ->defaultLocation(latitude: 52.8027, longitude: -1.0546)
                ->afterStateUpdated(function (Set $set, ?array $state): void {
                    $set('latitude', $state['lat']);
                    $set('longitude', $state['lng']);
                })
                ->afterStateHydrated(function ($state, $record, Set $set): void {
                    $set('location', ['lat' => $record->latitude, 'lng' => $record->longitude]);
                })
                ->extraStyles([
                    'min-height: 150vh',
                    'border-radius: 50px'
                ])
                ->liveLocation(true, true, 10000) // Updates live location every 10 seconds
                ->showMarker()
                ->markerColor("#22c55eff")
                ->showFullscreenControl()
                ->showZoomControl()
                ->draggable()
                ->tilesUrl("https://tile.openstreetmap.de/{z}/{x}/{y}.png")
                ->zoom(15)
                ->detectRetina()
                ->showMyLocationButton()
                ->extraTileControl([])
                ->extraControl([
                    'zoomDelta'           => 1,
                    'zoomSnap'            => 2,
                ])
           ]);
    }
    ...
}

您可以使用的其他测试Geoman形状的选项是

<?php
namespace App\Filament\Resources;
use Filament\Resources\Resource;
use Filament\Resources\Forms\Form;
use Doode\MapPicker\Fields\Map;
...

class FilamentResource extends Resource
{
    ...
    public static function form(Form $form)
    {
        return $form->schema([
            Map::make('location')
                ->label('Location')
                ->columnSpanFull()
                ->defaultLocation(latitude: 52.8027, longitude: -1.0546)
                ->afterStateUpdated(function (Set $set, ?array $state): void {
                    if ($state) {
                        $set('coordinates', json_encode($state));
                    }
                })
                ->afterStateHydrated(function ($state, $record, Set $set): void {
                    $set('coordinates', $record?->geom);
                })
                ->extraStyles([
                    'min-height: 50vh',
                    'border-radius: 50px'
                ])
                ->liveLocation(true, true, 10000) // Updates live location every 10 seconds
                ->showMarker() //true or false
                ->markerColor("#22c55eff")
                ->showFullscreenControl() //true or false
                ->showZoomControl() //true or false
                ->draggable() //true or false
                ->tilesUrl("https://tile.openstreetmap.de/{z}/{x}/{y}.png")
                ->zoom(10)
                ->detectRetina()
                ->showMyLocationButton()
                ->extraTileControl([])
                ->extraControl([
                    'zoomDelta'           => 1,
                    'zoomSnap'            => 2,
                ]),
           
            Textarea::make('coordinates')->columnSpanFull()     
                
           ]);
           
           
    }
    ...
}

liveLocation选项

liveLocation方法接受三个参数

  1. bool $send: 确定是否发送用户的实时位置。
  2. bool $realtime: 控制是否定期将实时位置发送到服务器。
  3. int $milliseconds: 设置用户位置更新并发送到服务器的时间间隔(以毫秒为单位)。

示例

Map::make('location')
    ->liveLocation(true, true, 10000)  // Updates live location every 10 seconds
    ->showMarker()
    ->draggable()

如果您希望通过操作或更改其他输入值后更新地图位置和标记,可以使用以下方法刷新地图

use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\Actions;
use Filament\Support\Enums\VerticalAlignment;

Actions::make([
    Action::make('Set Default Location')
        ->icon('heroicon-m-map-pin')
        ->action(function (Set $set, $state, $livewire): void {
            $set('location', ['lat' => '52.8027', 'lng' => '-1.0546']);
            $set('latitude', '52.8027');
            $set('longitude', '-1.0546');
            $livewire->dispatch('refreshMap');
        })
])->verticalAlignment(VerticalAlignment::Start);

作为信息列表字段的使用

MapEntry信息列表字段显示一个地图。

use Doode\MapPicker\Infolists\MapEntry;

public static function infolist(Infolist $infolist): Infolist
{
    return $infolist
        ->schema([
            MapEntry::make('location')
                ->extraStyles([
                    'min-height: 50vh',
                    'border-radius: 50px'
                ])
                ->state(fn ($record) => ['lat' => $record?->latitude, 'lng' => $record?->longitude])
                ->showMarker()
                ->markerColor("#22c55eff")
                ->showFullscreenControl()
                ->draggable(false)
                ->zoom(15),

            .....
        ]);
}

处理地图位置的使用指南

本节解释了如何使用此软件包在您的应用程序中处理和显示地图位置。

步骤1:定义您的数据库模式

确保您的数据库表包括纬度和经度列。这对于存储您位置坐标是必要的。您可以将表模式定义为以下内容

$table->double('latitude')->nullable();
$table->double('longitude')->nullable();

步骤2:检索和设置坐标

当加载记录时,确保您正确检索和设置纬度和经度值。在您的表单组件中使用以下方法

->afterStateHydrated(function ($state, $record, Set $set): void {
    $set('location', ['lat' => $record?->latitude, 'lng' => $record?->longitude]);
})

步骤3:添加纬度和经度的表单字段

向您的表单添加纬度和经度的隐藏表单字段。这确保了值存在但不对用户可见

TextInput::make('latitude')
    ->hiddenLabel()
    ->hidden(),

TextInput::make('longitude')
    ->hiddenLabel()
    ->hidden()

如果您希望以只读格式显示这些值,将hidden()替换为readOnly()

替代方法:使用单个位置属性

如果您希望将位置作为单个字段处理,您可以在模型中定义一个自定义属性。此方法避免了需要单独的纬度和经度列

class YourModel extends Model
{
    protected function location(): Attribute
    {
        return Attribute::make(
            get: fn (mixed $value, array $attributes) => [
                'latitude' => $attributes['latitude'],
                'longitude' => $attributes['longitude']
            ],
            set: fn (array $value) => [
                'latitude' => $value['latitude'],
                'longitude' => $value['longitude']
            ],
        );
    }
}

此方法将纬度和经度封装在单个位置属性中,简化了您的代码。

许可证

MIT许可证 © Doode

安全

我们非常重视安全。如果您发现任何错误或安全问题,请通过我们的GitHub问题跟踪器向我们报告,以帮助我们维护一个安全的项目。您也可以直接通过doode@doode.com.br联系我们。

贡献

我们欢迎贡献!贡献使开源社区成为一个如此棒的学习、灵感和创作的场所。您所提供的任何贡献都将受到高度赞赏。如果您有任何改进建议,请fork仓库并创建一个pull request。您也可以简单地通过标签“enhancement”打开一个issue。别忘了给项目加个星标!再次感谢!

  1. fork项目
  2. 创建您的功能分支(git checkout -b feature/AmazingFeature
  3. 提交您的更改(git commit -m '添加一些AmazingFeature'
  4. 推送到分支(git push origin feature/AmazingFeature
  5. 打开Pull Request