├── .gitignore ├── src ├── LatlongServiceProvider.php ├── Map │ ├── Yandex.php │ ├── AbstractMap.php │ ├── Tencent.php │ ├── Amap.php │ ├── Baidu.php │ └── Google.php ├── Extension.php └── Latlong.php ├── composer.json ├── LICENSE ├── resources └── views │ └── latlong.blade.php └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | phpunit.phar 3 | /vendor 4 | composer.phar 5 | composer.lock 6 | *.project 7 | .idea/ -------------------------------------------------------------------------------- /src/LatlongServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadViewsFrom($extension->views(), 'laravel-admin-latlong'); 22 | 23 | Admin::booting(function () { 24 | Form::extend('latlong', Latlong::class); 25 | Show\Field::macro('latlong', Extension::showField()); 26 | }); 27 | } 28 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel-admin-ext/latlong", 3 | "description": "Latitude & Longitude selector", 4 | "type": "library", 5 | "keywords": ["laravel-admin", "extension"], 6 | "homepage": "https://github.com/laravel-admin-ext/latlong", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "z-song", 11 | "email": "zosong@126.com" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=7.0.0", 16 | "encore/laravel-admin": "~1.6" 17 | }, 18 | "require-dev": { 19 | "phpunit/phpunit": "~6.0" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "Encore\\Admin\\Latlong\\": "src/" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "Encore\\Admin\\Latlong\\LatlongServiceProvider" 30 | ] 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jens Segers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /resources/views/latlong.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 | 7 | @include('admin::form.error') 8 | 9 |
10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 | @if($provider != 'yandex') 18 |
19 |
20 | 21 | 22 | 23 | 24 |
25 |
26 | @endif 27 | 28 |
29 | 30 |
31 | 32 |
33 | 34 | @include('admin::form.help-block') 35 | 36 |
37 |
38 | -------------------------------------------------------------------------------- /src/Map/Yandex.php: -------------------------------------------------------------------------------- 1 | getParams('zoom')} 28 | }); 29 | 30 | var myPlacemark = new ymaps.Placemark([lat.val(), lng.val()], { 31 | }, { 32 | preset: 'islands#redDotIcon', 33 | draggable: true 34 | }); 35 | 36 | myPlacemark.events.add(['dragend'], function (e) { 37 | lat.val(myPlacemark.geometry.getCoordinates()[0]); 38 | lng.val(myPlacemark.geometry.getCoordinates()[1]); 39 | }); 40 | 41 | myMap.geoObjects.add(myPlacemark); 42 | }); 43 | 44 | } 45 | 46 | init('{$id['lat']}{$id['lng']}'); 47 | })(); 48 | EOT; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Map/AbstractMap.php: -------------------------------------------------------------------------------- 1 | api = sprintf($this->api, $key); 32 | } 33 | } 34 | 35 | /** 36 | * @return array 37 | */ 38 | public function getAssets() 39 | { 40 | return [$this->api]; 41 | } 42 | 43 | public function getParams($field = null) { 44 | if($field) { 45 | return isset($this->params[$field]) ? $this->params[$field] : null; 46 | } 47 | return $this->params; 48 | } 49 | 50 | /** 51 | * Set true to automatically get the current position from the browser on page load 52 | * @param $bool 53 | * @return $this 54 | */ 55 | public function setAutoPosition($bool) { 56 | $this->autoPosition = $bool; 57 | return $this; 58 | } 59 | 60 | public function setParams($params) { 61 | $this->params = $params; 62 | return $this; 63 | } 64 | 65 | /** 66 | * @param array $id 67 | * @param bool $autoPosition 68 | * @return string 69 | */ 70 | abstract public function applyScript(array $id); 71 | } -------------------------------------------------------------------------------- /src/Extension.php: -------------------------------------------------------------------------------- 1 | Map\Baidu::class, 19 | 'tencent' => Map\Tencent::class, 20 | 'amap' => Map\Amap::class, 21 | 'google' => Map\Google::class, 22 | 'yandex' => Map\Yandex::class, 23 | ]; 24 | 25 | /** 26 | * @var Map\AbstractMap 27 | */ 28 | protected static $provider; 29 | 30 | /** 31 | * @param string $name 32 | * @return Map\AbstractMap 33 | */ 34 | public static function getProvider($name = '') 35 | { 36 | if (static::$provider) { 37 | return static::$provider; 38 | } 39 | 40 | $name = Extension::config('default', $name); 41 | $args = Extension::config("providers.$name", []); 42 | 43 | return static::$provider = new static::$providers[$name](...array_values($args)); 44 | } 45 | 46 | /** 47 | * @return \Closure 48 | */ 49 | public static function showField() 50 | { 51 | return function ($lat, $lng, $height = 300, $zoom = 16) { 52 | 53 | return $this->unescape()->as(function () use ($lat, $lng, $height, $zoom) { 54 | 55 | $lat = $this->{$lat}; 56 | $lng = $this->{$lng}; 57 | $id = ['lat' => 'lat', 'lng' => 'lng']; 58 | Admin::script(Extension::getProvider() 59 | ->setParams([ 60 | 'zoom' => $zoom 61 | ]) 62 | ->applyScript($id)); 63 | 64 | return << 66 |
67 | 68 |
69 |
70 | 71 |
72 | 73 | 74 |
75 | 76 |
77 | HTML; 78 | }); 79 | }; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Map/Tencent.php: -------------------------------------------------------------------------------- 1 | getParams('zoom')} 29 | }); 30 | 31 | var marker = new qq.maps.Marker({ 32 | position: center, 33 | draggable: true, 34 | map: map 35 | }); 36 | 37 | if( ! lat.val() || ! lng.val()) { 38 | var citylocation = new qq.maps.CityService({ 39 | complete : function(result){ 40 | map.setCenter(result.detail.latLng); 41 | marker.setPosition(result.detail.latLng); 42 | } 43 | }); 44 | 45 | citylocation.searchLocalCity(); 46 | } 47 | 48 | qq.maps.event.addListener(map, 'click', function(event) { 49 | marker.setPosition(event.latLng); 50 | }); 51 | 52 | qq.maps.event.addListener(marker, 'position_changed', function(event) { 53 | var position = marker.getPosition(); 54 | lat.val(position.getLat()); 55 | lng.val(position.getLng()); 56 | }); 57 | 58 | var ap = new qq.maps.place.Autocomplete(document.getElementById("search-{$id['lat']}{$id['lng']}")); 59 | 60 | var searchService = new qq.maps.SearchService({ 61 | map : map 62 | }); 63 | 64 | qq.maps.event.addListener(ap, "confirm", function(res){ 65 | searchService.search(res.value); 66 | }); 67 | } 68 | 69 | init('{$id['lat']}{$id['lng']}'); 70 | })(); 71 | EOT; 72 | } 73 | } -------------------------------------------------------------------------------- /src/Map/Amap.php: -------------------------------------------------------------------------------- 1 | getParams('zoom')}, 21 | center: [lng.val() || 0, lat.val() || 0],//中心点坐标 22 | viewMode:'3D',//使用3D视图 23 | }); 24 | 25 | var marker = new AMap.Marker({ 26 | map: map, 27 | draggable: true, 28 | position: [lng.val() || 0, lat.val() || 0], 29 | }) 30 | 31 | map.on('click', function(e) { 32 | marker.setPosition(e.lnglat); 33 | 34 | lat.val(e.lnglat.getLat()); 35 | lng.val(e.lnglat.getLng()); 36 | }); 37 | 38 | marker.on('dragend', function (e) { 39 | lat.val(e.lnglat.getLat()); 40 | lng.val(e.lnglat.getLng()); 41 | }); 42 | 43 | if( ! lat.val() || ! lng.val()) { 44 | map.plugin('AMap.Geolocation', function () { 45 | geolocation = new AMap.Geolocation(); 46 | map.addControl(geolocation); 47 | geolocation.getCurrentPosition(); 48 | AMap.event.addListener(geolocation, 'complete', function (data) { 49 | marker.setPosition(data.position); 50 | 51 | lat.val(data.position.getLat()); 52 | lng.val(data.position.getLng()); 53 | }); 54 | }); 55 | } 56 | 57 | AMap.plugin('AMap.Autocomplete',function(){ 58 | var autoOptions = { 59 | input:"search-{$id['lat']}{$id['lng']}" 60 | }; 61 | var autocomplete= new AMap.Autocomplete(autoOptions); 62 | 63 | AMap.event.addListener(autocomplete, "select", function(data){ 64 | map.setZoomAndCenter(18, data.poi.location); 65 | marker.setPosition(data.poi.location); 66 | lat.val(data.poi.location.lat); 67 | lng.val(data.poi.location.lng); 68 | }); 69 | }); 70 | } 71 | 72 | init('map_{$id['lat']}{$id['lng']}'); 73 | })(); 74 | EOT; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 经纬度选择器/Latitude and longitude selector 2 | ====== 3 | 4 | 这个扩展用来帮助你在form表单中选择经纬度,用来替代`Laravel-admin`中内置的`Form\Field\Map`组件, 组件支持的地图包括`Google map`、`百度地图`、`高德地图`、`腾讯地图`、`Yandex map`. 5 | 6 | This extension is used to help you select the latitude and longitude in the form, which is used to replace the `Laravel-admin` built in `Form\Field\Map` component. The supported maps include `Google map`, `Baidu map`, `AMap`, `Tencent Map`, `Yandex map`. 7 | 8 | ## Installation 9 | 10 | ```bash 11 | // For laravel-admin 1.x 12 | composer require laravel-admin-ext/latlong:1.x -vvv 13 | 14 | // For laravel-admin 2.x 15 | composer require laravel-admin-ext/latlong:2.x -vvv 16 | ``` 17 | 18 | ## Configuration 19 | 20 | Open `config/admin.php` and add the following configuration to the extensions section: 21 | 22 | ```php 23 | 24 | 'extensions' => [ 25 | 26 | 'latlong' => [ 27 | 28 | // Whether to enable this extension, defaults to true 29 | 'enable' => true, 30 | 31 | // Specify the default provider 32 | 'default' => 'google', 33 | 34 | // According to the selected provider above, fill in the corresponding api_key 35 | 'providers' => [ 36 | 37 | 'google' => [ 38 | 'api_key' => '', 39 | ], 40 | 41 | 'yandex' => [ 42 | 'api_key' => '', 43 | ], 44 | 45 | 'baidu' => [ 46 | 'api_key' => 'xck5u2lga9n1bZkiaXIHtMufWXQnVhdx', 47 | ], 48 | 49 | 'tencent' => [ 50 | 'api_key' => 'VVYBZ-HRJCX-NOJ4Z-ZO3PU-ZZA2J-QPBBT', 51 | ], 52 | 53 | 'amap' => [ 54 | 'api_key' => '3693fe745aea0df8852739dac08a22fb', 55 | ], 56 | ] 57 | ] 58 | ] 59 | 60 | ``` 61 | 62 | ## Usage 63 | 64 | Suppose you have two fields `latitude` and `longitude` in your table that represent latitude and longitude, then use the following in the form: 65 | 66 | ```php 67 | $form->latlong('latitude', 'longitude', 'Position'); 68 | 69 | // Set the map height 70 | $form->latlong('latitude', 'longitude', 'Position')->height(500); 71 | 72 | // Set the map zoom 73 | $form->latlong('latitude', 'longitude', 'Position')->zoom(16); 74 | 75 | // Set default position 76 | $form->latlong('latitude', 'longitude', 'Position')->default(['lat' => 90, 'lng' => 90]); 77 | ``` 78 | 79 | Use in show page 80 | 81 | ```php 82 | $show->field('Position')->latlong('lat_column', 'long_column', $height = 400, $zoom = 16); 83 | ``` 84 | 85 | ## Donate 86 | 87 | 如果觉得这个项目帮你节约了时间,不妨支持一下;) 88 | 89 | ![-1](https://cloud.githubusercontent.com/assets/1479100/23287423/45c68202-fa78-11e6-8125-3e365101a313.jpg) 90 | 91 | License 92 | ------------ 93 | Licensed under [The MIT License (MIT)](LICENSE). 94 | -------------------------------------------------------------------------------- /src/Map/Baidu.php: -------------------------------------------------------------------------------- 1 | getParams('zoom')}); 21 | map.enableScrollWheelZoom(true); 22 | 23 | var marker = new BMap.Marker(point); 24 | map.addOverlay(marker); 25 | marker.enableDragging(); 26 | 27 | if( ! lat.val() || ! lng.val()) { 28 | var geolocation = new BMap.Geolocation(); 29 | geolocation.getCurrentPosition(function(e){ 30 | if(this.getStatus() == BMAP_STATUS_SUCCESS){ 31 | map.panTo(e.point); 32 | marker.setPosition(e.point); 33 | 34 | lat.val(e.point.lat); 35 | lng.val(e.point.lng); 36 | 37 | } 38 | else { 39 | console.log('failed'+this.getStatus()); 40 | } 41 | },{enableHighAccuracy: true}) 42 | } 43 | 44 | map.addEventListener("click", function(e){ 45 | marker.setPosition(e.point); 46 | lat.val(e.point.lat); 47 | lng.val(e.point.lng); 48 | }); 49 | 50 | marker.addEventListener("dragend", function(e){ 51 | lat.val(e.point.lat); 52 | lng.val(e.point.lng); 53 | }); 54 | 55 | var ac = new BMap.Autocomplete( 56 | {"input" : "search-{$id['lat']}{$id['lng']}" 57 | ,"location" : map 58 | }); 59 | 60 | var address; 61 | ac.addEventListener("onconfirm", function(e) { //鼠标点击下拉列表后的事件 62 | var _value = e.item.value; 63 | address = _value.province + _value.city + _value.district + _value.street + _value.business; 64 | setPlace(); 65 | }); 66 | 67 | function setPlace(){ 68 | function myFun(){ 69 | var pp = local.getResults().getPoi(0).point; 70 | map.centerAndZoom(pp, {$this->getParams('zoom')}); 71 | 72 | marker.setPosition(pp); 73 | lat.val(pp.lat); 74 | lng.val(pp.lng); 75 | } 76 | var local = new BMap.LocalSearch(map, { 77 | onSearchComplete: myFun 78 | }); 79 | local.search(address); 80 | } 81 | } 82 | 83 | init('map_{$id['lat']}{$id['lng']}'); 84 | 85 | })(); 86 | EOT; 87 | } 88 | } -------------------------------------------------------------------------------- /src/Latlong.php: -------------------------------------------------------------------------------- 1 | Extension::getProvider()->getAssets()]; 48 | } 49 | 50 | /** 51 | * Latlong constructor. 52 | * 53 | * @param string $column 54 | * @param array $arguments 55 | */ 56 | public function __construct($column, $arguments) 57 | { 58 | $this->column['lat'] = (string)$column; 59 | $this->column['lng'] = (string)$arguments[0]; 60 | 61 | array_shift($arguments); 62 | 63 | $this->label = $this->formatLabel($arguments); 64 | $this->id = $this->formatId($this->column); 65 | } 66 | 67 | /** 68 | * Set map height. 69 | * 70 | * @param int $height 71 | * @return $this 72 | */ 73 | public function height(int $height) 74 | { 75 | $this->height = $height; 76 | 77 | return $this; 78 | } 79 | 80 | 81 | /** 82 | * Set map zoom. 83 | * 84 | * @param int $zoom 85 | * @return $this 86 | */ 87 | public function zoom(int $zoom) 88 | { 89 | $this->zoom = $zoom; 90 | 91 | return $this; 92 | } 93 | 94 | /** 95 | * Set true to automatically get the current position from the browser on page load 96 | * @param $bool 97 | * @return Latlong 98 | */ 99 | public function setAutoPosition($bool) { 100 | $this->autoPosition = $bool; 101 | return $this; 102 | } 103 | 104 | /** 105 | * {@inheritdoc} 106 | * 107 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string 108 | */ 109 | public function render() 110 | { 111 | $this->script = Extension::getProvider() 112 | ->setParams([ 113 | 'zoom' => $this->zoom 114 | ]) 115 | ->setAutoPosition($this->autoPosition) 116 | ->applyScript($this->id); 117 | 118 | $variables = [ 119 | 'height' => $this->height, 120 | 'provider' => Extension::config('default'), 121 | ]; 122 | 123 | $this->addVariables($variables); 124 | 125 | return parent::fieldRender(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/Map/Google.php: -------------------------------------------------------------------------------- 1 | autoPosition)?'1':'0'; 18 | return <<getParams('zoom')}, 28 | center: LatLng, 29 | panControl: false, 30 | zoomControl: true, 31 | scaleControl: true, 32 | mapTypeId: google.maps.MapTypeId.ROADMAP 33 | } 34 | 35 | var container = document.getElementById("map_"+name); 36 | var map = new google.maps.Map(container, options); 37 | 38 | if (navigator.geolocation && {$autoPosition}) { 39 | navigator.geolocation.getCurrentPosition(function(position) { 40 | var pos = { 41 | lat: position.coords.latitude, 42 | lng: position.coords.longitude 43 | }; 44 | map.setCenter(pos); 45 | marker.setPosition(pos); 46 | 47 | lat.val(position.coords.latitude); 48 | lng.val(position.coords.longitude); 49 | 50 | }, function() { 51 | 52 | }); 53 | } 54 | 55 | var marker = new google.maps.Marker({ 56 | position: LatLng, 57 | map: map, 58 | title: 'Drag Me!', 59 | draggable: true 60 | }); 61 | 62 | google.maps.event.addListener(marker, "position_changed", function(event) { 63 | var position = marker.getPosition(); 64 | 65 | lat.val(position.lat()); 66 | lng.val(position.lng()); 67 | }); 68 | 69 | google.maps.event.addListener(map, 'click', function(event) { 70 | marker.setPosition(event.latLng); 71 | }); 72 | 73 | var autocomplete = new google.maps.places.Autocomplete( 74 | document.getElementById("search-{$id['lat']}{$id['lng']}") 75 | ); 76 | autocomplete.bindTo('bounds', map); 77 | 78 | google.maps.event.addListener(autocomplete, 'place_changed', function() { 79 | var place = autocomplete.getPlace(); 80 | var location = place.geometry.location; 81 | 82 | if (place.geometry.viewport) { 83 | map.fitBounds(place.geometry.viewport); 84 | } else { 85 | map.setCenter(location); 86 | map.setZoom(18); 87 | } 88 | 89 | marker.setPosition(location); 90 | 91 | lat.val(location.lat()); 92 | lng.val(location.lng()); 93 | }); 94 | } 95 | 96 | init('{$id['lat']}{$id['lng']}'); 97 | })(); 98 | EOT; 99 | } 100 | } 101 | --------------------------------------------------------------------------------