@@ -10,12 +10,11 @@ Camera animation modes
10
10
11
11
12
12
``` jsx
13
- import { Divider , Text } from ' @rneui/base' ;
13
+ import { CheckBox , Divider , Slider , Text } from ' @rneui/base' ;
14
14
import {
15
15
Camera ,
16
16
CameraAnimationMode ,
17
17
CameraBounds ,
18
- CameraPadding ,
19
18
CircleLayer ,
20
19
Logger ,
21
20
MapView ,
@@ -48,80 +47,48 @@ const initialCoordinate: Coordinate = {
48
47
longitude: - 73.984638 ,
49
48
};
50
49
51
- const zeroPadding: CameraPadding = {
52
- paddingTop: 0 ,
53
- paddingBottom: 0 ,
54
- paddingLeft: 0 ,
55
- paddingRight: 0 ,
56
- };
57
- const evenPadding: CameraPadding = {
58
- paddingTop: 40 ,
59
- paddingBottom: 40 ,
60
- paddingLeft: 40 ,
61
- paddingRight: 40 ,
62
- };
63
- const minZoomLevel = 8 ;
64
- const maxZoomLevel = 16 ;
65
-
66
- const randPadding = (): CameraPadding => {
67
- const randNum = () => {
68
- const items = [0 , 150 , 300 ];
69
- return items[Math .floor (Math .random () * items .length )];
70
- };
71
-
72
- return {
73
- paddingTop: randNum (),
74
- paddingBottom: randNum (),
75
- paddingLeft: randNum (),
76
- paddingRight: randNum (),
77
- };
78
- };
79
-
80
50
const toPosition = (coordinate: Coordinate): Position => {
81
51
return [coordinate .longitude , coordinate .latitude ];
82
52
};
83
53
54
+ const rand = () => Math .random () * 0.008 ;
55
+
84
56
const CameraAnimation = () => {
85
- const [animationMode , setAnimationMode ] =
86
- useState< CameraAnimationMode> (' moveTo' );
57
+ const [easing , setEasing ] = useState< CameraAnimationMode> (' easeTo' );
87
58
const [coordinates , setCoordinates ] = useState< Coordinate[]> ([
88
59
initialCoordinate,
89
60
]);
90
- const [padding , setPadding ] = useState< CameraPadding> (zeroPadding);
91
-
92
- const paddingDisplay = useMemo (() => {
93
- return ` L ${ padding .paddingLeft } | R ${ padding .paddingRight } | T ${ padding .paddingTop } | B ${ padding .paddingBottom } ` ;
94
- }, [padding]);
95
-
96
- const move = useCallback (
97
- (_animationMode : CameraAnimationMode , shouldCreateMultiple : boolean ) => {
98
- setAnimationMode (_animationMode);
99
-
100
- if (shouldCreateMultiple) {
101
- const _centerCoordinate = {
102
- latitude: initialCoordinate .latitude + Math .random () * 0.2 ,
103
- longitude: initialCoordinate .longitude + Math .random () * 0.2 ,
104
- };
105
- const _coordinates = Array (10 )
106
- .fill (0 )
107
- .map ((_ ) => {
108
- return {
109
- latitude: _centerCoordinate .latitude + Math .random () * 0.2 ,
110
- longitude: _centerCoordinate .longitude + Math .random () * 0.2 ,
111
- };
112
- });
113
- setCoordinates (_coordinates);
114
- } else {
115
- setCoordinates ([
116
- {
117
- latitude: initialCoordinate .latitude + Math .random () * 0.2 ,
118
- longitude: initialCoordinate .longitude + Math .random () * 0.2 ,
119
- },
120
- ]);
121
- }
122
- },
123
- [],
124
- );
61
+ const [paddingLeft , setPaddingLeft ] = useState (0 );
62
+ const [paddingRight , setPaddingRight ] = useState (0 );
63
+ const [paddingTop , setPaddingTop ] = useState (0 );
64
+ const [paddingBottom , setPaddingBottom ] = useState (0 );
65
+ const [minZoom , setMinZoom ] = useState< number | undefined > (undefined );
66
+ const [maxZoom , setMaxZoom ] = useState< number | undefined > (undefined );
67
+
68
+ const move = useCallback ((kind : ' center' | ' bounds' ) => {
69
+ if (kind === ' bounds' ) {
70
+ const _centerCoordinate = {
71
+ latitude: initialCoordinate .latitude + rand (),
72
+ longitude: initialCoordinate .longitude + rand (),
73
+ };
74
+ const _coordinates = Array (10 )
75
+ .fill (0 )
76
+ .map ((_ ) => {
77
+ return {
78
+ latitude: _centerCoordinate .latitude + rand (),
79
+ longitude: _centerCoordinate .longitude + rand (),
80
+ };
81
+ });
82
+ setCoordinates (_coordinates);
83
+ } else if (kind === ' center' ) {
84
+ setCoordinates ([
85
+ {
86
+ latitude: initialCoordinate .latitude + rand (),
87
+ longitude: initialCoordinate .longitude + rand (),
88
+ },
89
+ ]);
90
+ }
91
+ }, []);
125
92
126
93
const features = useMemo ((): Feature< Point > [] => {
127
94
return coordinates .map ((p ) => {
@@ -164,31 +131,118 @@ const CameraAnimation = () => {
164
131
}
165
132
}, [coordinates]);
166
133
167
- const locationDisplay = useMemo (() => {
168
- if (coordinates .length > 1 ) {
169
- const ne = centerOrBounds .bounds ? .ne .map ((n ) => n .toFixed (3 ));
170
- const sw = centerOrBounds .bounds ? .sw .map ((n ) => n .toFixed (3 ));
171
- return ` ne ${ ne} | sw ${ sw} ` ;
172
- } else if (coordinates .length === 1 ) {
173
- const lon = coordinates[0 ].longitude .toFixed (4 );
174
- const lat = coordinates[0 ].latitude .toFixed (4 );
175
- return ` lon ${ lon} | lat ${ lat} ` ;
176
- } else {
177
- throw new Error (' invalid location passed' );
178
- }
179
- }, [coordinates, centerOrBounds]);
134
+ const easingCheckBox = useCallback (
135
+ (value : CameraAnimationMode , label : string ) => {
136
+ const isChecked = value === easing;
137
+ return (
138
+ < View
139
+ style= {{
140
+ flex: 0 ,
141
+ flexDirection: ' row' ,
142
+ alignItems: ' center' ,
143
+ }}
144
+ >
145
+ < CheckBox
146
+ checked= {isChecked}
147
+ center= {true }
148
+ onIconPress= {() => setEasing (value)}
149
+ containerStyle= {{
150
+ backgroundColor: ' transparent' ,
151
+ marginRight: - 4 ,
152
+ }}
153
+ / >
154
+ < Text
155
+ style= {{
156
+ flex: 0 ,
157
+ color: isChecked ? colors .primary .blue : undefined ,
158
+ }}
159
+ >
160
+ {label}
161
+ < / Text >
162
+ < / View>
163
+ );
164
+ },
165
+ [easing],
166
+ );
167
+
168
+ const paddingCounter = useCallback (
169
+ (value: number, setValue : (value : number ) => void , label: string) => {
170
+ return (
171
+ < View style= {{ flex: 1 , paddingHorizontal: 10 }}>
172
+ < View style= {{ flex: 0 , alignItems: ' center' }}>
173
+ < Text > {label}< / Text >
174
+ < Text style= {{ fontWeight: ' bold' }}> {` ${ Math .round (value)} ` }< / Text >
175
+ < / View>
176
+ < Slider
177
+ thumbStyle= {{
178
+ backgroundColor: ' black' ,
179
+ width: 15 ,
180
+ height: 15 ,
181
+ }}
182
+ value= {value}
183
+ minimumValue= {0 }
184
+ maximumValue= {500 }
185
+ onSlidingComplete= {(_value ) => setValue (_value)}
186
+ / >
187
+ < / View>
188
+ );
189
+ },
190
+ [],
191
+ );
192
+
193
+ const zoomLimitCounter = useCallback (
194
+ (
195
+ value: number | undefined ,
196
+ setValue : (value ?: number ) => void ,
197
+ label: string,
198
+ ) => {
199
+ return (
200
+ < View style= {{ flex: 1 , paddingHorizontal: 10 }}>
201
+ < View style= {{ flex: 0 , alignItems: ' center' }}>
202
+ < Text > {label}< / Text >
203
+ < Text style= {{ fontWeight: ' bold' }}> {` ${
204
+ value ?? ' Not set'
205
+ }` }</Text>
206
+ </View>
207
+ <Slider
208
+ thumbStyle={{
209
+ backgroundColor: 'black',
210
+ width: 15,
211
+ height: 15,
212
+ }}
213
+ value={value}
214
+ minimumValue={-1}
215
+ maximumValue={20}
216
+ onSlidingComplete={(_value) => {
217
+ if (_value < 0) {
218
+ setValue(undefined);
219
+ } else {
220
+ setValue(Math.round(_value));
221
+ }
222
+ }}
223
+ />
224
+ </View>
225
+ );
226
+ },
227
+ [],
228
+ );
180
229
181
230
return (
182
231
<>
183
232
<MapView style={styles.map}>
184
233
<Camera
185
234
{...centerOrBounds}
186
235
zoomLevel={12}
187
- minZoomLevel= {minZoomLevel}
188
- maxZoomLevel= {maxZoomLevel}
189
- padding= {padding}
236
+ minZoomLevel={minZoom}
237
+ maxZoomLevel={maxZoom}
238
+ padding={{
239
+ paddingTop,
240
+ paddingBottom,
241
+ paddingLeft,
242
+ paddingRight,
243
+ }}
190
244
animationDuration={800}
191
- animationMode= {animationMode }
245
+ animationMode={easing }
192
246
/>
193
247
194
248
{features.map((feature) => {
@@ -204,53 +258,39 @@ const CameraAnimation = () => {
204
258
<SafeAreaView>
205
259
<View style={styles.sheet}>
206
260
<View style={styles.content}>
207
- < Text style= {styles .fadedText } > centerCoordinate < / Text >
261
+ <Text style={styles.sectionText}>Coordinate </Text>
208
262
<View style={styles.buttonRow}>
209
- < Button title= " Flight" onPress= {() => move (' flyTo' , false )} / >
210
- < Button title= " Ease" onPress= {() => move (' easeTo' , false )} / >
211
- < Button title= " Linear" onPress= {() => move (' linearTo' , false )} / >
212
- < Button title= " Instant" onPress= {() => move (' moveTo' , false )} / >
263
+ <Button title="Center" onPress={() => move('center')} />
264
+ <Button title="Bounds" onPress={() => move('bounds')} />
213
265
</View>
214
266
215
267
<Divider style={styles.divider} />
216
268
217
- < Text style= {styles .fadedText } > bounds < / Text >
218
- < View style= {styles .buttonRow }>
219
- < Button title = " Flight " onPress = {() => move ( ' flyTo ' , true )} / >
220
- < Button title = " Ease " onPress = {() => move ( ' easeTo ' , true )} / >
221
- < Button title = " Linear " onPress = {() => move ( ' linearTo ' , true )} / >
222
- < Button title = " Instant " onPress = {() => move ( ' moveTo' , true )} / >
269
+ <Text style={styles.sectionText}>Easing </Text>
270
+ <View style={[ styles.buttonRow, { marginBottom: -6 }] }>
271
+ {easingCheckBox('easeTo ', 'Ease')}
272
+ {easingCheckBox('linearTo ', 'Linear')}
273
+ {easingCheckBox('flyTo ', 'Fly')}
274
+ {easingCheckBox( 'moveTo', 'Move')}
223
275
</View>
224
276
225
277
<Divider style={styles.divider} />
226
278
227
- < Text style= {styles .fadedText }> padding< / Text >
228
- < View style= {styles .buttonRow }>
229
- < Button
230
- title= " Zero"
231
- onPress= {() => {
232
- setPadding (zeroPadding);
233
- }}
234
- / >
235
- < Button
236
- title= " Even"
237
- onPress= {() => {
238
- setPadding (evenPadding);
239
- }}
240
- / >
241
- < Button
242
- title= " Random"
243
- onPress= {() => {
244
- setPadding (randPadding ());
245
- }}
246
- / >
279
+ <Text style={styles.sectionText}>Padding</Text>
280
+ <View style={[styles.buttonRow, { marginTop: 6 }]}>
281
+ {paddingCounter(paddingTop, setPaddingTop, 'Top')}
282
+ {paddingCounter(paddingBottom, setPaddingBottom, 'Bottom')}
283
+ {paddingCounter(paddingLeft, setPaddingLeft, 'Left')}
284
+ {paddingCounter(paddingRight, setPaddingRight, 'Right')}
247
285
</View>
248
286
249
287
<Divider style={styles.divider} />
250
288
251
- < Text style= {styles .fadedText }> info< / Text >
252
- < Text > position: {locationDisplay}< / Text >
253
- < Text > padding: {paddingDisplay}< / Text >
289
+ <Text style={styles.sectionText}>Zoom limits</Text>
290
+ <View style={[styles.buttonRow, { marginTop: 6 }]}>
291
+ {zoomLimitCounter(minZoom, setMinZoom, 'Min')}
292
+ {zoomLimitCounter(maxZoom, setMaxZoom, 'Max')}
293
+ </View>
254
294
</View>
255
295
</View>
256
296
</SafeAreaView>
@@ -263,22 +303,23 @@ const styles = StyleSheet.create({
263
303
flex: 1,
264
304
},
265
305
sheet: {
266
- paddingTop: 10 ,
267
306
paddingHorizontal: 10,
307
+ marginBottom: -10,
268
308
},
269
309
content: {
270
310
padding: 10,
271
311
},
312
+ sectionText: {
313
+ fontSize: 10,
314
+ color: 'gray',
315
+ },
272
316
buttonRow: {
273
317
flex: 0,
274
318
flexDirection: 'row',
275
- justifyContent: ' space-around ' ,
319
+ justifyContent: 'space-evenly ',
276
320
},
277
321
divider: {
278
- marginVertical: 10 ,
279
- },
280
- fadedText: {
281
- color: ' gray' ,
322
+ marginVertical: 8,
282
323
},
283
324
});
284
325
0 commit comments