jamesil / nova-google-polygon
A Laravel Nova Google polygon field.
Installs: 198
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/jamesil/nova-google-polygon
Requires
- php: ^8.1
- ext-bcmath: *
- illuminate/support: ^9.0|^10.0|^11.0
- laravel/nova: ^4.0|^5.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.8
- pestphp/pest: ^1.21
- phpunit/phpunit: ^9.1
This package is not auto-updated.
Last update: 2026-01-13 10:09:39 UTC
README
A Laravel Nova field for creating and editing polygons on Google Maps.
Features
- Interactive polygon drawing and editing on Google Maps
- Support for multiple polygon points
- Real-time coordinate updates
- Customizable map center and zoom
- Laravel model casting support
- Polygon containment checking utilities
Requirements
- PHP 8.1 or higher
- Laravel Nova 4.0 or 5.0
- Laravel 9.0 or higher
- Google Maps API key with Maps JavaScript API enabled
Version Compatibility
| Laravel Nova | Laravel | PHP | Package Version |
|---|---|---|---|
| 5.0 | 10.x - 11.x | 8.1+ | 1.x |
| 4.0 | 9.x - 11.x | 8.1+ | 1.x |
Installation
Install the package via Composer:
composer require jamesil/nova-google-polygon
Configuration
The package merges its default configuration automatically. You only need to publish the config file if you want to customize the defaults.
- Publish the configuration file (optional):
php artisan vendor:publish --provider="Jamesil\NovaGooglePolygon\FieldServiceProvider"
- Set up your Google Maps API key:
First, create a Google Cloud project and enable the Maps JavaScript API:
- Visit Google Cloud Console
- Create a new project or select an existing one
- Enable the Maps JavaScript API
- Create credentials to get your API key
- Add environment variables:
Add these variables to your .env file:
NOVA_GOOGLE_POLYGON_API_KEY=your-google-maps-api-key NOVA_GOOGLE_POLYGON_CENTER_LAT=48.858361 NOVA_GOOGLE_POLYGON_CENTER_LNG=2.336164
Usage
Basic Field Usage
Add the field to your Nova resource:
use Jamesil\NovaGooglePolygon\GooglePolygon; class Location extends Resource { public function fields(Request $request) { return [ ID::make()->sortable(), Text::make('Name'), GooglePolygon::make('Coverage Area', 'coverage_area'), ]; } }
Database Setup
The polygon data is stored as JSON. Create a JSON column in your migration:
Schema::create('locations', function (Blueprint $table) { $table->id(); $table->string('name'); $table->json('coverage_area')->nullable(); $table->timestamps(); });
Model Casting
Use the provided cast to automatically handle polygon data:
use Jamesil\NovaGooglePolygon\Casts\AsPolygon; class Location extends Model { protected $casts = [ 'coverage_area' => AsPolygon::class, ]; }
Working with Polygons
The package provides utility classes for working with polygon data:
use Jamesil\NovaGooglePolygon\Support\Polygon; use Jamesil\NovaGooglePolygon\Support\Point; // Create a polygon $polygon = new Polygon([ ['lat' => 48.858361, 'lng' => 2.336164], ['lat' => 48.859361, 'lng' => 2.337164], ['lat' => 48.857361, 'lng' => 2.338164], ]); // Check if a point is inside the polygon $point = new Point(48.858500, 2.337000); $isInside = $polygon->contain($point); // returns true // Get bounding box $boundingBox = $polygon->getBoundingBox(); // Get min/max coordinates $minLat = $polygon->getMinLatitude(); $maxLat = $polygon->getMaxLatitude(); $minLng = $polygon->getMinLongitude(); $maxLng = $polygon->getMaxLongitude();
Advanced Example
Here's a complete example of using the field with a taxi pickup zone system:
// Nova Resource use Jamesil\NovaGooglePolygon\GooglePolygon; class PickupZone extends Resource { public function fields(Request $request) { return [ ID::make()->sortable(), Text::make('Zone Name'), Number::make('Base Fare'), Boolean::make('Active'), GooglePolygon::make('Pickup Area', 'pickup_area'), ]; } } // Model use Jamesil\NovaGooglePolygon\Casts\AsPolygon; use Jamesil\NovaGooglePolygon\Support\Point; class PickupZone extends Model { protected $casts = [ 'pickup_area' => AsPolygon::class, 'active' => 'boolean', ]; public function isPickupAllowed($latitude, $longitude) { if (!$this->active || !$this->pickup_area) { return false; } $point = new Point($latitude, $longitude); return $this->pickup_area->contain($point); } public static function findAvailableZone($latitude, $longitude) { return static::where('active', true) ->get() ->first(function ($zone) use ($latitude, $longitude) { return $zone->isPickupAllowed($latitude, $longitude); }); } public function getTotalFare($distance, $duration) { // Calculate fare based on zone's base fare return $this->base_fare + ($distance * 2.5) + ($duration * 0.5); } }
API Reference
Polygon Class Methods
contain(Point|array $point): Check if a point is inside the polygonpointOnVertex(Point|array $point): Check if a point is on a polygon vertexgetBoundingBox(): Get the bounding box coordinatesgetMinLatitude(),getMaxLatitude(): Get latitude boundsgetMinLongitude(),getMaxLongitude(): Get longitude boundsgetPoints(): Get all polygon pointssetPoints(array $points): Set polygon points
Point Class Methods
fromArray(array $input): Create a point from arraytoArray(): Convert point to arraytoJson(): Convert point to JSON
Testing
Run the test suite:
composer test
Credits
- James Embling
- Based on the original work by YieldStudio
License
The MIT License (MIT). Please see License File for more information.