10-Jul-2023
.
Admin
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 :
I hope it can help you...
#Laravel 10