How To Add a Geofencing in Map using Laravel?
Teams applying “How To Add a Geofencing in Map using Laravel?” in a production project can use the related Monitask article to record implementation, review and debugging time, then compare that effort with tests and shipped functionality instead of treating activity as performance by itself.
Before copying the example into a live application, confirm version-specific behaviour with the official Laravel website and test it against the project’s actual database and runtime.
Hi dev,
In this post, we will learn how to add a geofencing in map using laravel. you can see How can add a geofence or custom markers in laravel. In this article, we will implement a How to implement geofencing in map using laravel. you can understand a concept of How to use geofencing in map using laravel.
how to add a geofencing in map using laravel,How can add a geofence or custom markers in laravel,How to implement geofencing in map using laravel,How to use geofencing in map using laravel,how do you implement a geofence map in laravel,add geofencing in map using laravel Step 1: Install Laravel
first of all we need to get fresh Laravel 10 version application using bellow command, So open your terminal OR command prompt and run bellow command:
composer create-project laravel/laravel example-app
Step 2: install package
So open your terminal OR command prompt and run bellow command:
composer require grimzy/laravel-mysql-spatial
Step 3: set config go to config/app.php => provider and past bellow code :
Grimzy\LaravelMysqlSpatial\SpatialServiceProvider::class,
Step 4: Create "zones" table basically, it will created "zones" table :
Migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateZonesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('zones', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable();
$table->string('city_full_address')->nullable();
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->string('city_latitude')->nullable();
$table->string('city_longitude')->nullable();
$table->string('zone_center_latitude')->nullable();
$table->string('zone_center_longitude')->nullable();
$table->polygon('map_polygon')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('zones');
}
}
Step 5: Create Route
In this is step we need to create custom route. so open your routes/web.php file and add following route.
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
// zone
Route::get('/zone', [HomeController::class, 'index'])->name('index');
Route::get('zone/{id}/assign/map_polygon', [HomeController::class, 'assignMapPolygon'])->name('zone.assign.map_polygon');
Route::post('zone/assign/map_polygon/store', [HomeController::class, 'assignMapPolygonStore'])->name('zone.map_polygon.store');
Route::post('zone/assign/map_polygon/clear', [HomeController::class, 'assignMapPolygon'])->name('zone.map_polygon.clear');
Route::post('zone/map_polygon/clear', [HomeController::class, 'assignMapPolygonClear'])->name('zone.map_polygon.clear');
// rider
Route::get('/rider', [HomeController::class, 'createRider'])->name('rider.create');
Route::post('/rider/store', [HomeController::class, 'createRiderStore'])->name('rider.create.store');
Step 6: Create Controller in this step, we need to create HomeController and add following code on that file:
app/Http/Controllers/HomeController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Zone;
use App\Models\Rider;
use DataTables;
use DB;
use Exception;
use Throwable;
use Log;
use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;
class HomeController extends Controller
{
public function index(Request $request){
if ($request->ajax()) {
$data = Zone::select('*');
return Datatables::of($data)
->addIndexColumn()
->addColumn('action', function($row){
$btn = '<a href="'.route('zone.assign.map_polygon',$row->id).'" type="button" class="btn btn-primary btn-padding-fs btn-margin ml-1" data-toggle="tooltip" data-placement="bottom" data-original-title="Assign Geofencing"><b>Assign Geofencing</b></a><br>';
return $btn;
})
->rawColumns(['action'])
->make(true);
}
return view('welcome');
}
public function assignMapPolygon($id){
$zone = Zone::find($id);
if (empty($zone) || is_null($zone)) {
return redirect()->route('index');
}
$currentPolygon = $currentPolygonLatLng = [];
// check if polygon points exist than only create polygon array
if(!empty($zone->map_polygon) && method_exists($zone->map_polygon,'getLineStrings') && !empty($zone->map_polygon->getLineStrings()) && isset($zone->map_polygon->getLineStrings()[0]) && !empty($zone->map_polygon->getLineStrings()[0]) ){
foreach ($zone->map_polygon->getLineStrings()[0]->getPoints() as $value) {
$currentPolygonLatLng[] = [
'lat'=>$value->getLat(),
'lng'=>$value->getLng()
];
}
}
// if polygon points exist than create polygon object for frontend map
if(!empty($currentPolygonLatLng)){
$currentPolygon =[
"path"=> $currentPolygonLatLng,
"strokeColor"=> "#1f9d57",
"strokeOpacity"=> 0.8,
"strokeWeight"=> 2,
"fillColor"=> "#00FF00",
"fillOpacity"=> 0.4,
"city_latitude"=>$zone->city_latitude,
"city_longitude"=>$zone->city_longitude,
"zone_center_latitude"=>$zone->zone_center_latitude ?? ($zone->city_latitude ?? 28.7041),
"zone_center_longitude"=>$zone->zone_center_longitude ?? ($zone->city_longitude ?? 77.1025),
"zone_name"=>$zone->name,
"id"=>$zone->id,
"label"=>$zone->name."[$zone->city_full_address]",
];
}
// check if city is added than pick city lat long else New Delhi lat long
$mapCenter = [
'lat'=>!empty($zone->city_latitude) ? $zone->city_latitude : 28.7041,
'lng'=>!empty($zone->city_longitude) ? $zone->city_longitude : 77.1025
];
return view('mapPolygon',compact('id','zone','mapCenter','currentPolygon'));
}
public function assignMapPolygonStore(Request $request){
$input = $request->all();
//DB Transaction start
DB::beginTransaction();
$zone = Zone::find($input['zone_id']);
// declare a point array to assign in linestring
$polygon_points = [];
foreach ($input['map_polygon'] as $value) {
// create a new point array for each polygon points
$polygon_points[] = new Point($value['lat'], $value['lng']);
}
// pass first position value as last to complete the polygon
$polygon_points[] = new Point($input['map_polygon'][0]['lat'], $input['map_polygon'][0]['lng']);
// create a polygon from linestring and point array & assign polygon to zone object
$zone->map_polygon = new Polygon([new LineString($polygon_points)]);
$zone_center = isset($input['polygon_center']) && !empty($input['polygon_center']) ? $input['polygon_center'] : [];
$zone->zone_center_latitude = $zone_center['lat'] ?? NULL;
$zone->zone_center_longitude = $zone_center['lng'] ?? NULL;
// save updated polygon
$zone->save();
DB::commit();
return response()->json(['success'=>'Zone Geofencing saved successfully']);
try {
}catch (Exception $e) {
DB::rollback();
Log::error($e);
report($e);
return response()->json(['dberror'=>config('celcius.operation_dbtransaction_message')]);
} catch (Throwable $e) {
DB::rollback();
Log::error($e);
report($e);
return response()->json(['dberror'=>config('celcius.operation_dbtransaction_message')]);
//throw $e;
}
//DB Transaction End
}
public function assignMapPolygonClear(Request $request){
$input = $request->all();
$zone = Zone::find($input['zone_id']);
//DB Transaction start
DB::beginTransaction();
try {
$zone->map_polygon = NULL;
$zone->zone_center_latitude = NULL;
$zone->zone_center_longitude = NULL;
$zone->save();
DB::commit();
return response()->json(['success'=>'Zone Geofencing cleared successfully']);
} catch (Exception $e) {
DB::rollback();
Log::error($e);
report($e);
return response()->json(['dberror'=>config('celcius.operation_dbtransaction_message')]);
} catch (Throwable $e) {
DB::rollback();
Log::error($e);
report($e);
return response()->json(['dberror'=>config('celcius.operation_dbtransaction_message')]);
//throw $e;
}
//DB Transaction End
}
public function createRider(){
return view('riderCreate');
}
public function createRiderStore(Request $request){
$input = $request->all();
$latitude = $input['from_latitude'];
$longitude = $input['from_longitude'];
$location = findZoneByLatLng($latitude,$longitude);
if(!empty($location)){
$input['zone_id'] = $location->id;
Rider::create($input);
return redirect()->route('index');
}else{
return "<center><h1>No Location Found</h1></center>";
}
}
}
Step 7: Create models here, we need to create models. so let's create one by one files:
app/models/User.php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
app/models/Zone.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;
use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;
class Zone extends Model
{
use HasFactory;
use SpatialTrait;
protected $fillable = [
'name',
'city_full_address',
'city',
'state',
'city_latitude',
'city_longitude',
'zone_center_latitude',
'zone_center_longitude',
'map_polygon',
];
//geofancing related table fields needs to declare here
protected $spatialFields = [
//data type: polygon , default null
'map_polygon'
];
public function scopeIsDelete($query)
{
return $query->where('deleted', '0');
}
public function scopeContainsLatLng($query,$lat,$lng){
return $query->contains('map_polygon', new Point($lat, $lng));
}
}
app/models/Rider.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Rider extends Model
{
use HasFactory;
protected $fillable = [
'name',
'mobile_number',
'zone_id'
];
}
Step 8: Create Helper Files here, we need to create Helper files. so let's create files:
app/Http/helpers.php
use App\Models\Zone;
function getAllZoneLatLngForGmap($city=NULL,$state=NULL,$dcHubId = NULL){
$latLongs = [];
$allZoneQuery = Zone::isDelete()->whereNotNull('map_polygon');
!empty($city) && $allZoneQuery->where('city',$city);
!empty($state) && $allZoneQuery->where('state',$state);
!empty($dcHubId) && $allZoneQuery->where('dc_hub_id',$dcHubId);
$allZone = $allZoneQuery->cursor();
if(!empty($allZone)){
foreach($allZone as $zone){
if(!empty($zone->map_polygon) && method_exists($zone->map_polygon,'getLineStrings') && !empty($zone->map_polygon->getLineStrings()) && isset($zone->map_polygon->getLineStrings()[0]) && !empty($zone->map_polygon->getLineStrings()[0]) ){
$currentPolygonLatLng = [];
foreach ($zone->map_polygon->getLineStrings()[0]->getPoints() as $value) {
$currentPolygonLatLng[] = [
'lat'=>$value->getLat(),
'lng'=>$value->getLng()
];
}
if(!empty($currentPolygonLatLng)){
$latLongs[$zone->id] = [
"id"=>$zone->id,
"city_latitude"=>$zone->city_latitude,
"city_longitude"=>$zone->city_longitude,
"zone_center_latitude"=>$zone->zone_center_latitude??$zone->city_latitude,
"zone_center_longitude"=>$zone->zone_center_longitude??$zone->city_longitude,
"zone_name"=>$zone->name,
"label"=>$zone->name." [$zone->city]",
"path"=> $currentPolygonLatLng,
"strokeColor"=> "#FF0000",
"strokeOpacity"=> 0.8,
"strokeWeight"=> 2,
"fillColor"=> "#FF0000",
"fillOpacity"=> 0.35
];
}
}
}
}
return $latLongs;
}
function findZoneByLatLng($lat = NULL, $lng = NULL){
return (!empty($lat) && !empty($lng)) ? Zone::isDelete()->containsLatLng($lat, $lng)->first() : [];
}
?>
Step 9: Create Blade Files here, we need to create blade files. so let's create one by one files:
resources/views/welcome.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Laravel 8 Datatables Tutorial - ItSolutionStuff.com </title>
<meta name="csrf-token" content="{{ csrf_token() }}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.0/jquery.validate.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js"></script>
</head>
<body>
<div class="container">
<br><br><h1>Laravel 8 Datatables Tutorial ItSolutionStuff.com</h1><br><br>
<a href="{{ route('rider.create') }}" type="button" style="float:right;" class="btn btn-success mb-2">Create Rider</a><br>
<table class="table table-bordered data-table">
<thead>
<tr>
<th>No</th>
<th>Name</th>
<th>City Full Address</th>
<th width="100px">Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</body>
<script type="text/javascript">
$(function () {
var table = $('.data-table').DataTable({
processing: true,
serverSide: true,
ajax: "{{ route('index') }}",
columns: [
{data: 'id', name: 'id'},
{data: 'name', name: 'name'},
{data: 'city_full_address', name: 'city_full_address'},
{data: 'action', name: 'action', orderable: false, searchable: false},
]
});
});
</script>
</html>
resources/views/mapPolygon.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<style type="text/css">
#map {
height: 100%;
}
#map-canvas {
height: 750px;
margin: 0px;
padding: 0px
}
.pac-card {
background-color: #fff;
border: 0;
border-radius: 2px;
box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.3);
margin: 10px;
padding: 0 0.5em;
font: 400 18px Roboto, Arial, sans-serif;
overflow: hidden;
font-family: Roboto;
padding: 0;
}
#pac-container {
padding-bottom: 12px;
margin-right: 12px;
}
.pac-controls {
display: inline-block;
padding: 5px 11px;
}
.pac-controls label {
font-family: Roboto;
font-size: 13px;
font-weight: 300;
}
#searchMapCityOnly {
background-color: #fff;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
margin-left: 12px;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 400px;
margin-bottom: 15px;
}
#searchMapCityOnly:focus {
border-color: #4d90fe;
}
#floating-panel {
position: absolute;
top: 50px;
right: 9%;
z-index: 5;
background-color: #ffffffd1;
padding: 5px;
text-align: center;
font-family: "Roboto", "sans-serif";
line-height: 30px;
}
#floating-panel #save_polygon{
display: none;
}
#floating-panel #clear_polygon{
display: none;
}
</style>
</head>
<body>
<div class="content-body">
<div class="card">
<div class="card-header border-bottom mx-2 px-0">
<h4 class="card-title pb-1">{{!empty($zone->map_polygon) ? 'Update' : 'Assign'}} Zone Geofencing : {{$zone->name}} {{!empty($zone->city_full_address) ? "[".$zone->city_full_address."]" : ""}}</h4>
</div>
<div class="card-body">
<input type="hidden" name="zone_id" id="zone_id" value="{{ $id }}">
<input type="hidden" name="map_polygon" id="polygon" value="">
<input type="hidden" id="city" value="">
<input type="hidden" id="state" value="">
<input type="hidden" id="latitude" value="">
<input type="hidden" id="longitude" value="">
<div class="row">
<div class="col-md-12 text-center mt-1">
<input id="searchMapCityOnly" class="controls" type="text" placeholder="Search Cities" />
<div id="floating-panel">
<button type="button" id="save_polygon" onclick="save_polygon()" class="btn btn-icon btn-success waves-effect waves-light" data-toggle="tooltip" data-placement="top" data-original-title="Save Zone Geofencing">Save</button>
<button type="button" id="clear_polygon" onclick="clear_polygon()" class="btn btn-icon btn-danger waves-effect waves-light" data-toggle="tooltip" data-placement="top" data-original-title="Remove Zone Geofencing">Clear</button>
</div>
<div id="map-canvas" class="google_map_initialize"></div>
</div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://maps.googleapis.com/maps/api/js?key={{ env('GOOGLE_MAP_API_KEY') }}&libraries=places,drawing,geometry&callback=initMap" async defer></script>
<script type="text/javascript">
var map; // Global declaration of the map
var drawingManager;
var newPolygon = [];
var newPolygonCenter = {};
let allZonePolygon = @json(getAllZoneLatLngForGmap($zone->city,$zone->state,$zone->dc_hub_id));
var map_center = { lat:"{{$mapCenter['lat']}}",lng:"{{$mapCenter['lng']}}" };
// NOTE: DO NOT CHANGE FUNCTION NAME, this function name is set in
function google_map_initialize() {
var myLatlng = new google.maps.LatLng({{$mapCenter['lat']}},{{$mapCenter['lng']}});
var myOptions = {
zoom: 12,
center: myLatlng,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
//This custom function get's bound pincodes by polygon area
google.maps.Polygon.prototype.getBoundingBox = function() {
var bounds = new google.maps.LatLngBounds();
this.getPath().forEach(function(element,index) {
bounds.extend(element)
});
return(bounds);
};
//This custom function calculates center of polygon
google.maps.Polygon.prototype.getApproximateCenter = function() {
var boundsHeight = 0,
boundsWidth = 0,
centerPoint,
heightIncr = 0,
maxSearchLoops,
maxSearchSteps = 10,
n = 1,
northWest,
polygonBounds = this.getBoundingBox(),
testPos,
widthIncr = 0;
// Get polygon Centroid
centerPoint = polygonBounds.getCenter();
if (google.maps.geometry.poly.containsLocation(centerPoint, this)) {
// Nothing to do Centroid is in polygon use it as is
return centerPoint;
} else {
maxSearchLoops = maxSearchSteps / 2;
// Calculate NorthWest point so we can work out height of polygon NW->SE
northWest = new google.maps.LatLng(polygonBounds.getNorthEast().lat(), polygonBounds.getSouthWest().lng());
// Work out how tall and wide the bounds are and what our search increment will be
boundsHeight = google.maps.geometry.spherical.computeDistanceBetween(northWest, polygonBounds.getSouthWest());
heightIncr = boundsHeight / maxSearchSteps;
boundsWidth = google.maps.geometry.spherical.computeDistanceBetween(northWest, polygonBounds.getNorthEast());
widthIncr = boundsWidth / maxSearchSteps;
// Expand out from Centroid and find a point within polygon at 0, 90, 180, 270 degrees
for (; n <= maxSearchLoops; n++) {
// Test point North of Centroid
testPos = google.maps.geometry.spherical.computeOffset(centerPoint, (heightIncr * n), 0);
if (google.maps.geometry.poly.containsLocation(testPos, this)) {
break;
}
// Test point East of Centroid
testPos = google.maps.geometry.spherical.computeOffset(centerPoint, (widthIncr * n), 90);
if (google.maps.geometry.poly.containsLocation(testPos, this)) {
break;
}
// Test point South of Centroid
testPos = google.maps.geometry.spherical.computeOffset(centerPoint, (heightIncr * n), 180);
if (google.maps.geometry.poly.containsLocation(testPos, this)) {
break;
}
// Test point West of Centroid
testPos = google.maps.geometry.spherical.computeOffset(centerPoint, (widthIncr * n), 270);
if (google.maps.geometry.poly.containsLocation(testPos, this)) {
break;
}
}
return(testPos);
}
};
map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
setCurrentPolygon();
// setAllZonePolygon();
var autocomplete_options = {
componentRestrictions: {country: "IN"}
};
var searchMapCityOnly = document.getElementById('searchMapCityOnly');
var autocompleteCities = new google.maps.places.Autocomplete(searchMapCityOnly,autocomplete_options);
google.maps.event.addListener(autocompleteCities, 'place_changed', function () {
var place = this.getPlace();
if(place.geometry !== undefined){
if(place.geometry.location !== undefined){
map.fitBounds(place.geometry.viewport);
}else{
map.setCenter(place.geometry.location);
map.setZoom(12);
}
latFrom = place.geometry.location.lat();
lngFrom = place.geometry.location.lng();
// empty the value once selected from dropdown
document.getElementById('latitude').value ='';
document.getElementById('longitude').value ='';
document.getElementById('city').value='';
document.getElementById('state').value ='';
// set latitude longitude from geometry
document.getElementById('latitude').value = place.geometry.location.lat();
document.getElementById('longitude').value = place.geometry.location.lng();
for (const component of place.address_components) {
const addressType = component.types[0];
if (componentForm[addressType]) {
if (addressType == 'locality') {
const val = component[componentForm[addressType]];
document.getElementById('city').value = val;
}
if (addressType == 'administrative_area_level_1') {
const val = component[componentForm[addressType]];
document.getElementById('state').value = val;
}
}
}
}
});
$('.searchMapCityOnly').on('focus', function() {
selected = false;
}).on('blur', function() {
if (!selected) {
$(this).val('');
}
});
}
function checkMapLoaded() {
if (typeof google === "undefined") {
setTimeout(checkMapLoaded, 1000);
} else {
// do some work here
google_map_initialize();
}
}
checkMapLoaded();
// google.maps.event.addDomListener(window, 'load', google_map_initialize);
function setCurrentPolygon() {
const currentPolygon = @json($currentPolygon);
if(currentPolygon.path !== undefined){
const existingPolygon = new google.maps.Polygon(currentPolygon);
existingPolygon.setMap(map);
const marker = new google.maps.Marker({
position:new google.maps.LatLng(currentPolygon.zone_center_latitude, currentPolygon.zone_center_longitude),
map,
label: {
text: currentPolygon.zone_name,
color: "#203334",
fontWeight: "bold",
fontSize: "16px",
className: "badge badge-warning"
},
optimized: false,
});
map.setCenter(new google.maps.LatLng(currentPolygon.zone_center_latitude, currentPolygon.zone_center_longitude));
map.setZoom(13);
// newPolygon.push(existingPolygon);
$('#floating-panel').show();
$('#save_polygon').hide();
$('#clear_polygon').show();
setAllZonePolygon(currentPolygon.id);
}else{
$('#floating-panel').hide();
$('#save_polygon').hide();
$('#clear_polygon').hide();
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.POLYGON]
},
polygonOptions: {
editable: false
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, "overlaycomplete", function(event) {
var newShape = event.overlay;
newShape.type = event.type;
});
google.maps.event.addListener(drawingManager, "overlaycomplete", function(event) {
newPolygon = [];
newPolygonCenter = {};
var polygon_center = event.overlay.getApproximateCenter();
newPolygonCenter.lat = polygon_center.lat();
newPolygonCenter.lng = polygon_center.lng();
event.overlay.getPath().forEach(function(x){
newPolygon.push({'lat':x.lat(),'lng':x.lng()});
});
$('#save_polygon').show();
$('#clear_polygon').show();
$('#floating-panel').show();
// newPolygon
// $('#polygon').val(newPolygon);
});
setAllZonePolygon();
}
}
function setAllZonePolygon(exceptId){
if(allZonePolygon){
Object.values(allZonePolygon).forEach(function(newPolygon) {
if(exceptId !== undefined && exceptId != '' && exceptId == newPolygon.id){
}else{
new google.maps.Polygon(newPolygon).setMap(map);
new google.maps.Marker({
position:new google.maps.LatLng(newPolygon.zone_center_latitude, newPolygon.zone_center_longitude),
map,
label: {
text: newPolygon.zone_name,
color: "#ffffff",
fontWeight: "normal",
fontSize: "14px",
className: "badge badge-danger"
},
optimized: false,
});
}
});
}
}
function save_polygon(){
$('#floating-panel').hide();
$('#save_polygon').hide();
$('#clear_polygon').hide();
//iterate polygon vertices?
$.ajax({
type: "POST",
dataType: "json",
headers : {'X-CSRF-TOKEN': $('meta[name="csrf_token"]').attr('content')},
url: "{{route('zone.map_polygon.store')}}",
data: {"_token": "{{ csrf_token() }}",polygon_center:newPolygonCenter,map_polygon:newPolygon,zone_id: $('#zone_id').val()},
success: function(data){
if(!$.isEmptyObject(data.dberror)){
location.href = ($('#back_url').length && $('#back_url').val() != '') ? $('#back_url').val() : window.location;
}else{
location.href = ($('#back_url').length && $('#back_url').val() != '') ? $('#back_url').val() : window.location;
}
}
});
}
function clear_polygon(){
$('#floating-panel').hide();
$('#save_polygon').hide();
$('#clear_polygon').hide();
$.ajax({
type: "POST",
dataType: "json",
url: "{{route('zone.map_polygon.clear')}}",
data: {_token:'{{ csrf_token() }}',zone_id: $('#zone_id').val()},
success: function(data){
if(!$.isEmptyObject(data.dberror)){
location.reload(true);
}else{
location.reload();
}
}
});
}
function initMap() {
var mapProp= {
center:new google.maps.LatLng(51.508742,-0.120850),
zoom:5,
};
var map = new google.maps.Map(document.getElementById("googleMap"),mapProp);
}
</script>
</body>
</html>
resources/views/riderCreate.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<title></title>
</head>
<body>
<div class="container">
<br>
<center><h3>Create Rider</h3></center>
<form method="POST" action="{{ route('rider.create.store') }}">
@csrf
<div class="form-group">
<label>Rider Name</label>
<input type="text" name="name" class="form-control">
</div>
<div class="form-group">
<label>Rider Mobile Number</label>
<input type="text" name="mobile_number" class="form-control">
</div>
<div class="form-group">
<label>Assign Address</label>
<input type="text" id="searchMapInput" autocomplete="off" prevent-blank="1" class="form-control rm-r-br address_input" name="from_loc" placeholder="">
<input type="hidden" name="from_latitude" id="from_latitude" placeholder="">
<input type="hidden" name="from_longitude" id="from_longitude" placeholder="">
<input type="hidden" name="from_city" id="from_city" placeholder="">
<input type="hidden" name="from_state" id="from_state" placeholder="">
<input type="hidden" name="from_state_short" id="from_state_short" placeholder="">
<input type="hidden" name="from_pincode" id="from_pincode" placeholder="">
<input type="hidden" name="from_loc_transporter" id="from_loc_transporter" placeholder="">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://maps.googleapis.com/maps/api/js?key={{ env('GOOGLE_MAP_API_KEY') }}&libraries=places,drawing,geometry&callback=initMap" async defer></script>
<script type="text/javascript">
function initMap() {
var options = {
//types: ['(regions)'],
//types: ['(cities)'],
componentRestrictions: {country: "IN"}
};
var selected = false;
var input = document.getElementById('searchMapInput');
if (input) {
var autocompleteTo = new google.maps.places.Autocomplete(input,options);
//document.getElementById('searchMapInput1').value ='';
google.maps.event.addListener(autocompleteTo, 'place_changed', function () {
var place = this.getPlace();
document.getElementById('from_latitude').value ='';
document.getElementById('from_longitude').value ='';
document.getElementById('from_city').value='';
document.getElementById('from_state').value ='';
document.getElementById('from_state_short').value ='';
document.getElementById('from_pincode').value ='';
document.getElementById('from_loc_transporter').value ='';
latTo = place.geometry.location.lat();
lngTo = place.geometry.location.lng();
document.getElementById('from_latitude').value = latTo;
document.getElementById('from_longitude').value = lngTo;
for (const component of place.address_components) {
const addressType = component.types[0];
if (componentForm[addressType]) {
if (addressType == 'locality') {
const val = component[componentForm[addressType]];
document.getElementById('from_city').value = val;
}
if (addressType == 'administrative_area_level_1') {
const val = component[componentForm[addressType]];
document.getElementById('from_state').value = val;
}
if (addressType == 'administrative_area_level_1') {
const val = component[componentForm['administrative_area_level_2']];
document.getElementById('from_state_short').value = val;
}
if (addressType == 'postal_code') {
const val = component[componentForm[addressType]];
document.getElementById('from_pincode').value = val;
}
}
}
document.getElementById('from_loc_transporter').value =document.getElementById('from_city').value+', '+document.getElementById('from_state').value;
});
}
$('#searchMapInput').on('focus', function() {
selected = false;
}).on('blur', function(e) {
if (!selected) {
if($(this).attr('prevent-blank') == '1'){
setTimeout(function(){
if(autocompleteTo.getPlace().address_components !== undefined){}else{$('#searchMapInput').val('');}
},400);
}else{
$(this).val('');
}
}
});
var options = {
//types: ['(regions)'],
//types: ['(cities)'],
componentRestrictions: {country: "IN"}
};
}
</script>
</body>
</html>
Now we are ready to run our example so run bellow command so quick run:
php artisan serve
Now you can open bellow URL on your browser:
localhost:8000/zone
zone :
rider :
map_polygon :
- How to Notifications With database Driver in Laravel 11?
- How to Send Email Via Notification in Laravel 11?
- How to Install and Configure Laravel 11 Debugbar?
- How to Like Dislike System in Laravel 11?
- How to Paginate a Model with Relationship in Laravel 11?
- Laravel 11 Upload Files to Amazon S3 Example
- Laravel 11 Send WhatsApp Messages Example
- Laravel 11 Rest API Authentication Using JWT Tutorial