# 电子围栏
<!DOCTYPE html> <html> <style> #map { width: 760px; height: 400px; top: 10px; bottom: 0; } .search-button { display: inline-block; padding: 3px 20px; background-color: #4CAF50; /* 按钮背景颜色 */ color: white; /* 文字颜色 */ cursor: pointer; border-radius: 5px; /* 圆角 */ text-align: center; font-size: 16px; } .search-button:hover { background-color: #45a049; /* 鼠标悬停时的背景颜色 */ } </style> <body > <form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action=""> <div class="form-group"> <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label> <div class="col-xs-12 col-sm-8"> <input id="c-name" class="form-control" name="row[name]" type="text" value=""> </div> </div> <div class="form-group"> <label class="control-label col-xs-12 col-sm-2">{:__('Lnglat')}:</label> <div class="col-xs-12 col-sm-8"> <input id="c-lnglat" readonly class="form-control" name="row[lnglat]" type="text" value=""> </div> </div> <div class="form-group"> <label class="control-label col-xs-12 col-sm-2">{:__('搜索地址')}:</label> <div class="col-xs-12 col-sm-8"> <input id="addressInput" class="form-control" type="text" placeholder="输入地址"> </div> <span class="search-button" onclick="geocodeAddress()">搜索</span> </div> <div id="map"></div> <div class="form-group layer-footer"> <label class="control-label col-xs-12 col-sm-2"></label> <div class="col-xs-12 col-sm-8"> <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('保存')}</button> </div> </div> </form> </body> </html> <!--YOUR_API_KEY--> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAQX1s8K_pLW1pcEsd2H9NAADoHWi2_kbQ&libraries=drawing"></script> <script> function geocodeAddress() { var geocoder = new google.maps.Geocoder(); var address = document.getElementById('addressInput').value; geocoder.geocode({ 'address': address }, function(results, status) { if (status === 'OK') { map.setCenter(results[0].geometry.location); map.setZoom(15); // 设置缩放级别,以便更清晰地显示位置 // 清除之前的绘图(如果有) drawingManager.setDrawingMode(null); drawingManager.setMap(null); drawingManager.setMap(map); // 重新设置绘图工具 } else { alert('无法找到该地址:' + status); } }); } const map = new google.maps.Map(document.getElementById("map"), { center: { lat: -34.397, lng: 150.644 }, zoom: 8, }); const drawingManager = new google.maps.drawing.DrawingManager({ drawingMode: google.maps.drawing.OverlayType.MARKER, drawingControl: true, drawingControlOptions: { position: google.maps.ControlPosition.TOP_CENTER, drawingModes: [ google.maps.drawing.OverlayType.POLYGON, //绘制多边形围栏 // google.maps.drawing.OverlayType.MARKER, // google.maps.drawing.OverlayType.CIRCLE, // google.maps.drawing.OverlayType.POLYLINE, // google.maps.drawing.OverlayType.RECTANGLE, ], }, markerOptions: { icon: "https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png", }, circleOptions: { fillColor: "#ffff00", fillOpacity: 1, strokeWeight: 5, clickable: false, editable: true, zIndex: 1, }, }); drawingManager.setMap(map); // 获取电子围栏值 google.maps.event.addListener(drawingManager, 'polygoncomplete', function(poly) { polygon = poly; getPolygonCoordinates(); }); function getPolygonCoordinates() { var path = polygon.getPath(); var coordinates = []; for (var i = 0; i < path.getLength(); i++) { coordinates.push({ lat: path.getAt(i).lat(), lng: path.getAt(i).lng() }); } let arrobj = coordinates.map(item =>{ console.log(JSON.stringify(item)); return JSON.stringify(item) }) $("#c-lnglat").val(arrobj) console.log("多边形顶点坐标:", arrobj); } </script>
# 保存电子围栏数据
public function add(){ if (false === $this->request->isPost()) { return $this->view->fetch(); } $params = $this->request->post('row/a'); if (empty($params)) { $this->error(__('Parameter %s can not be empty', '')); } if(!$params['name']){ $this->error('请输入电子围栏名称'); } if(!$params['lnglat']){ $this->error('请先画电子围栏'); } // 去除开头和结尾的花括号 $str = trim($params['lnglat'], '{}'); // 分割字符串为单个项目 $items = explode('},{', $str); // 初始化一个空数组来存储结果 $result = []; // 遍历每个项目并将其转换为关联数组 foreach ($items as $item) { // 添加花括号以便json_decode可以解析 $item = '{' . $item . '}'; // 将字符串解析为关联数组 $arr = json_decode($item, true); // 将解析后的数组添加到结果数组中 $result[] = $arr; } // 输出结果 $params['lnglat'] =json_encode($result); var_dump($params); $this->success(); }
# 根据已知起点计算去是否在围栏内APi接口
$demo = getMapKm("34.723538,113.729059", "34.747021,113.658247", 1); if($demo == 0){ $this->error('起点不在电子围栏内'); } var_dump($demo); exit; /** * Undocumented function * 获取谷歌地图两个点之间的行车距离 * @Author Ixiangang * @DateTime 2024-07-25 * @param [type] $origin 起点 * @param [type] $destination 终点 * @param integer $enclosure 1 = 是否需要检测是否在电子围栏内 * @return void */ function getMapKm($origin, $destination, $enclosure = 0) { // 检测是不是在电子围栏内 if ($enclosure == 1) { $origin_arr = explode(',', $origin); $mapence = \think\Db::name('mapence')->column('lnglat', 'id'); foreach ($mapence as $v) { $vertices = json_decode($v, true); $enc[] = isPointInsidePolygon($origin_arr[0], $origin_arr[1], $vertices); } # 不在电子围内返回 0 if (!in_array(1, $enc)) { return 0; } } // 设置API key $apiKey = 'AIzaSyB1VvStv3DmL5yu3hqZccjifY8P6b4MrIc'; //替换为你的Google Maps API密钥 // 构建请求URL $url = 'https://maps.googleapis.com/maps/api/directions/json?origin=' . $origin . '&destination=' . $destination . '&key=' . $apiKey; // 使用file_get_contents发送请求,或者使用cURL库 $json_response = file_get_contents($url); // 解码JSON响应 $response = json_decode($json_response, true); // 检查响应是否成功 if ($response['status'] == 'OK') { // 提取路线数组 $routes = $response['routes']; // 假设我们只关心第一条路线 $route = $routes[0]; // 提取路线上的步骤数组 $legs = $route['legs']; // 假设我们只关心第一条路线的第一个步骤 $leg = $legs[0]; // 提取步骤的距离 $distance = $leg['distance']; $distance = $leg['distance']; // 输出距离 //echo "行车路线的距离是:" . $distance['text'] . "\n"; $value = $distance['value'] / 1000; //千米 return number_format($value, 1); } else { //echo "无法计算距离,请检查API请求是否成功。"; return 0; } } /** * 查看是否在电子围栏内 * @Author Ixiangang * @DateTime 2024-07-25 * @param [type] $point_lat 起点维度 * @param [type] $point_lng 起点经度 * @param [type] $vertices 画电子围栏经纬 * @return boolean */ function isPointInsidePolygon($point_lat, $point_lng, $vertices) { $x = $point_lat; $y = $point_lng; $inside = false; $count = count($vertices); for ($i = 0, $j = $count - 1; $i < $count; $j = $i++) { $xi = $vertices[$i]['lat']; $yi = $vertices[$i]['lng']; $xj = $vertices[$j]['lat']; $yj = $vertices[$j]['lng']; $intersect = (($yi > $y) != ($yj > $y)) && ($x < ($xj - $xi) * ($y - $yi) / ($yj - $yi) + $xi); if ($intersect) $inside = !$inside; } return $inside; }
# 谷歌文档地图
https://developers.google.com/maps/documentation/javascript/drawinglayer?hl=zh-cn#maps_drawing_tools-javascript