Skip to content

Commit 2fd1435

Browse files
authored
Merge pull request #19 from mostafaznv/dev
drag and drop polygons #17
2 parents 61b6ac1 + 3dc129c commit 2fd1435

10 files changed

Lines changed: 192 additions & 39 deletions

File tree

README.md

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -124,30 +124,34 @@ Using this package, you can use spatial fields in Laravel Nova.
124124
125125
## Map Field Methods
126126
127-
| method | Arguments | description |
128-
|-----------------------------|------------------------------------------|---------------------------------------------------------------------------------|
129-
| defaultLatitude | latitude <br> `float` | Specifies latitude of map on page load |
130-
| defaultLongitude | longitude <br> `float` | Specifies longitude of map on page load |
131-
| zoom | zoom <br> `integer` | Specifies default map zoom |
132-
| withoutZoomControl | status <br> `bool` `default: true` | Specifies whether zoom in/out button should display on map or not |
133-
| withoutZoomSlider | status <br> `bool` `default: true` | Specifies whether zoom slider should display on map or not |
134-
| withFullScreenControl | status <br> `bool` `default: true` | Specifies whether full screen button should display on map or not |
135-
| mapHeight | height <br> `integer` `default: 400` | Map's height |
136-
| hideDetailButton | status <br> `bool` `default: true` | Specifies whether **Show Details** button should appear on detail pages or not |
137-
| markerIcon | icon <br> `integer` `available: 1, 2, 3` | Marker icon |
138-
| withSearchBox | `boolean` | Specifies whether map has search box or not |
139-
| searchProvider | provider `MapSearchProvider` | |
140-
| searchProviderApiKey | apiKey `string` | Specifies api key for search provider, if needed |
141-
| withAutocompleteSearch | status `bool` `default: true` | Specifies whether search results should load immediately or not |
142-
| searchAutocompleteMinLength | minLength `int` | Specifies the minimum number of characters to trigger search action |
143-
| searchAutocompleteTimeout | timeout `int` | Specifies the minimum number of ms to wait before triggering search action |
144-
| searchLanguage | language `string` | Specifies preferable language |
145-
| searchPlaceholder | placeholder `string` | |
146-
| searchBoxType | type `MapSearchBoxType` | Using this item, you can specify type of search box (button, or text-field |
147-
| searchResultLimit | limit `int` | Specifies limit of results |
148-
| searchResultKeepOpen | status `boolean` | Specifies whether the results keep opened |
149-
| requiredOnCreate | status <br> `bool` `default: true` | Makes field required on creation |
150-
| requiredOnUpdate | status <br> `bool` `default: true` | Makes field required on update |
127+
| method | Arguments | description |
128+
|-----------------------------|------------------------------------------|--------------------------------------------------------------------------------|
129+
| defaultLatitude | latitude <br> `float` | Specifies latitude of map on page load |
130+
| defaultLongitude | longitude <br> `float` | Specifies longitude of map on page load |
131+
| zoom | zoom <br> `integer` | Specifies default map zoom |
132+
| withoutZoomControl | status <br> `bool` `default: true` | Specifies whether zoom in/out button should display on map or not |
133+
| withoutZoomSlider | status <br> `bool` `default: true` | Specifies whether zoom slider should display on map or not |
134+
| withFullScreenControl | status <br> `bool` `default: true` | Specifies whether full screen button should display on map or not |
135+
| mapHeight | height <br> `integer` `default: 400` | Map's height |
136+
| hideDetailButton | status <br> `bool` `default: true` | Specifies whether **Show Details** button should appear on detail pages or not |
137+
| markerIcon | icon <br> `integer` `available: 1, 2, 3` | Marker icon |
138+
| withSearchBox | `boolean` | Specifies whether map has search box or not |
139+
| searchProvider | provider `MapSearchProvider` | |
140+
| searchProviderApiKey | apiKey `string` | Specifies api key for search provider, if needed |
141+
| withAutocompleteSearch | status `bool` `default: true` | Specifies whether search results should load immediately or not |
142+
| searchAutocompleteMinLength | minLength `int` | Specifies the minimum number of characters to trigger search action |
143+
| searchAutocompleteTimeout | timeout `int` | Specifies the minimum number of ms to wait before triggering search action |
144+
| searchLanguage | language `string` | Specifies preferable language |
145+
| searchPlaceholder | placeholder `string` | |
146+
| searchBoxType | type `MapSearchBoxType` | Using this item, you can specify type of search box (button, or text-field |
147+
| searchResultLimit | limit `int` | Specifies limit of results |
148+
| searchResultKeepOpen | status `boolean` | Specifies whether the results keep opened |
149+
| withTransformation | status `boolean` | Specifies whether transport feature should be enable on polygons |
150+
| transformScale | status `boolean` | Using this method, you can enable/disable scaling features |
151+
| transformRotate | status `boolean` | Using this method, you can enable/disable rotating features |
152+
| transformStretch | status `boolean` | Using this method, you can enable/disable stretch option |
153+
| requiredOnCreate | status <br> `bool` `default: true` | Makes field required on creation |
154+
| requiredOnUpdate | status <br> `bool` `default: true` | Makes field required on update |
151155
152156
153157
## Config Properties
@@ -166,14 +170,18 @@ Using this package, you can use spatial fields in Laravel Nova.
166170
| search.enable | bool | true | Using this item, you can toggle displaying search box on maps |
167171
| search.provider | MapSearchProvider | OSM | Specifies search provider available providers: `OSM, MAPQUEST, PHOTON, PELIAS, BING, OPENCAGE` |
168172
| search.api-key | string | '' | Specifies API key if required |
169-
| search.autocomplete | boolean | false | Using this item, you can toggle autocomplete feature for search box |
173+
| search.autocomplete | bool | false | Using this item, you can toggle autocomplete feature for search box |
170174
| search.autocomplete-min-length | int | 2 | The minimum number of characters to trigger search |
171175
| search.autocomplete-timeout | int | 200 | The minimum number of ms to wait before triggering search action |
172176
| search.language | string | en-US | Specifies preferable language |
173177
| search.placeholder | string | Search for an address | Specifies placeholder for text input |
174178
| search.box-type | MapSearchBoxType | TEXT_FIELD | Specifies type of search box. available types: `BUTTON, TEXT_FIELD` |
175179
| search.limit | int | 5 | Specifies limit of results |
176-
| search.keep-open | boolean | false | Specifies whether the results keep opened |
180+
| search.keep-open | bool | false | Specifies whether the results keep opened |
181+
| transform.enable | bool | true | Using this item, you can toggle transforming polygons maps |
182+
| transform.scale | bool | true | Using this property, you can toggle scaling features |
183+
| transform.scale | bool | true | Using this property, you can toggle rotating features |
184+
| transform.stretch | bool | true | Using this property, you can enable/disable stretch option |
177185
178186
----
179187
@@ -183,6 +191,20 @@ This package uses [Laravel Eloquent Spatial](https://github.com/MatanYadaev/lara
183191
184192
----
185193
194+
## Tricks
195+
196+
### Transform Polygons
197+
198+
To transform polygons, You should press `Alt` (Option `⌥`) button and drag that polygon everywhere you want.
199+
200+
### Select Polygons
201+
202+
To select polygons (and modify them), You can press `Shift` button and then click on the polygon.
203+
By pressing the `Shift` key, drawing mode will be disabled and you can
204+
select every polygon you want.
205+
206+
----
207+
186208
## Complete Example
187209
```php
188210
<?php

config/config.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,4 +227,50 @@
227227

228228
'keep-open' => false,
229229
],
230+
231+
'transform' => [
232+
/*
233+
|--------------------------------------------------------------------------
234+
| Enable/Disable Transformation
235+
|--------------------------------------------------------------------------
236+
|
237+
| Using this item, you can toggle transforming polygons maps
238+
|
239+
*/
240+
241+
'enable' => true,
242+
243+
/*
244+
|--------------------------------------------------------------------------
245+
| Scale
246+
|--------------------------------------------------------------------------
247+
|
248+
| Using this property, you can toggle scaling features
249+
|
250+
*/
251+
252+
'scale' => true,
253+
254+
/*
255+
|--------------------------------------------------------------------------
256+
| Rotate
257+
|--------------------------------------------------------------------------
258+
|
259+
| Using this property, you can toggle rotating features
260+
|
261+
*/
262+
263+
'rotate' => true,
264+
265+
/*
266+
|--------------------------------------------------------------------------
267+
| Stretch
268+
|--------------------------------------------------------------------------
269+
|
270+
| Using this property, you can enable/disable stretch option
271+
|
272+
*/
273+
274+
'stretch' => true,
275+
]
230276
];

dist/css/field.css

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/field.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/field.js.LICENSE.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,15 @@ PERFORMANCE OF THIS SOFTWARE.
170170
* http://www.fpdf.org/en/script/script37.php
171171
*/
172172

173+
/**
174+
* @license
175+
* Lodash <https://lodash.com/>
176+
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
177+
* Released under MIT license <https://lodash.com/license>
178+
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
179+
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
180+
*/
181+
173182
/**
174183
* A class to parse color values
175184
* @author Stoyan Stefanov <sstoo@gmail.com>

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"watch-poll": "mix watch --watch-options-poll=1000",
88
"hot": "mix watch --hot",
99
"prod": "npm run production",
10-
"production": "mix --production"
10+
"production": "mix --production",
11+
"nova:install": "npm --prefix='../../vendor/laravel/nova' ci"
1112
},
1213
"dependencies": {
1314
"@vue/compiler-sfc": "^3.2.29",

resources/js/components/form-fields/MultiPolygonFormField.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@
4848
</ol-style>
4949
</ol-interaction-select>
5050

51+
<ol-interaction-transform
52+
:condition="isTransformable"
53+
:scale="field.transform.scale"
54+
:rotate="field.transform.rotate"
55+
:stretch="field.transform.stretch"
56+
/>
57+
5158
<ol-zoom-control v-if="withZoomControl" />
5259
<ol-zoomslider-control v-if="withZoomSlider" />
5360
<ol-fullscreen-control v-if="withFullScreenControl" />
@@ -60,8 +67,8 @@ import {FormField, HandlesValidationErrors} from 'laravel-nova'
6067
import HasMap from '../../mixins/HasMap'
6168
import PolygonMixin from '../../mixins/PolygonMixin'
6269
import {fromLonLat, toLonLat} from 'ol/proj'
63-
import {GeoJSON} from "ol/format";
64-
import HasSearchBox from "../../mixins/HasSearchBox";
70+
import {GeoJSON} from 'ol/format'
71+
import HasSearchBox from '../../mixins/HasSearchBox'
6572
6673
export default {
6774
mixins: [FormField, HandlesValidationErrors, HasMap, PolygonMixin, HasSearchBox],

resources/js/components/form-fields/PolygonFormField.vue

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</ol-tile-layer>
1515

1616
<ol-vector-layer :style="vectorStyle">
17-
<ol-source-vector :features="zones">
17+
<ol-source-vector ref="source" :features="zones">
1818
<ol-interaction-modify
1919
v-if="isEditable"
2020
@modifyend="onModifyEnd"
@@ -48,6 +48,13 @@
4848
</ol-style>
4949
</ol-interaction-select>
5050

51+
<ol-interaction-transform
52+
:condition="isTransformable"
53+
:scale="field.transform.scale"
54+
:rotate="field.transform.rotate"
55+
:stretch="field.transform.stretch"
56+
/>
57+
5158
<ol-zoom-control v-if="withZoomControl" />
5259
<ol-zoomslider-control v-if="withZoomSlider" />
5360
<ol-fullscreen-control v-if="withFullScreenControl" />
@@ -57,7 +64,7 @@
5764

5865
<script>
5966
import {FormField, HandlesValidationErrors} from 'laravel-nova'
60-
import {toLonLat, fromLonLat} from 'ol/proj';
67+
import {toLonLat, fromLonLat} from 'ol/proj'
6168
import {GeoJSON} from 'ol/format'
6269
import HasMap from '../../mixins/HasMap'
6370
import PolygonMixin from '../../mixins/PolygonMixin'
@@ -115,8 +122,8 @@ export default {
115122
}
116123
},
117124
118-
onModifyEnd(event) {
119-
const geometry = event.features.getArray()[0].getGeometry()
125+
onModifyEnd() {
126+
const geometry = this.$refs.source.source.getFeatures()[0].getGeometry()
120127
121128
this.setValue(geometry.getCoordinates())
122129
},

resources/js/mixins/PolygonMixin.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {Collection} from 'ol'
22
import {Fill, Stroke, Style} from 'ol/style'
3-
import {toLonLat, fromLonLat} from 'ol/proj'
4-
import {GeoJSON} from 'ol/format'
3+
import {altKeyOnly, shiftKeyOnly} from 'ol/events/condition'
54
import {getCenter} from 'ol/extent'
65
import {inject} from 'vue'
6+
import {debounce} from 'lodash'
77

88
export default {
99
data() {
@@ -15,6 +15,8 @@ export default {
1515
drawIsEnabled: true,
1616
modifyIsEnabled: false,
1717
selectCondition: null,
18+
altKeyIsDown: false,
19+
shiftKeyIsDown: false,
1820
geoJsonObject: {
1921
type: 'FeatureCollection',
2022
crs: {
@@ -33,7 +35,7 @@ export default {
3335
},
3436

3537
isDrawable() {
36-
return this.drawIsEnabled && !this.isReadonly
38+
return this.drawIsEnabled && !this.isReadonly && !this.altKeyIsDown && !this.shiftKeyIsDown
3739
},
3840

3941
isEditable() {
@@ -80,12 +82,26 @@ export default {
8082
this.modifyIsEnabled = event.selected.length > 0
8183

8284
this.selectedFeatures.value = event.target.getFeatures()
85+
},
86+
87+
isTransformable(evt) {
88+
this.altKeyIsDown = altKeyOnly(evt)
89+
this.shiftKeyIsDown = shiftKeyOnly(evt)
90+
91+
return this.field.transform.isEnabled && !this.isDrawable && this.altKeyIsDown
8392
}
8493
},
8594
created() {
8695
this.initZones()
8796

8897
const selectConditions = inject('ol-selectconditions')
8998
this.selectCondition = selectConditions.click
99+
},
100+
mounted() {
101+
if (this.$refs.map && this.field.transform.isEnabled) {
102+
this.$refs.map.map.on('pointerdrag', debounce((evt) => {
103+
this.onModifyEnd(evt)
104+
}, 300))
105+
}
90106
}
91107
}

0 commit comments

Comments
 (0)