flet-map 0.1.0.dev2__py3-none-any.whl → 0.2.0.dev45__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of flet-map might be problematic. Click here for more details.

Files changed (37) hide show
  1. flet_map/__init__.py +30 -19
  2. flet_map/circle_layer.py +46 -139
  3. flet_map/map.py +462 -604
  4. flet_map/map_layer.py +14 -20
  5. flet_map/marker_layer.py +83 -169
  6. flet_map/polygon_layer.py +95 -232
  7. flet_map/polyline_layer.py +85 -262
  8. flet_map/rich_attribution.py +48 -126
  9. flet_map/simple_attribution.py +24 -75
  10. flet_map/source_attribution.py +73 -0
  11. flet_map/tile_layer.py +224 -266
  12. flet_map/types.py +953 -0
  13. flet_map-0.2.0.dev45.dist-info/METADATA +66 -0
  14. flet_map-0.2.0.dev45.dist-info/RECORD +35 -0
  15. {flet_map-0.1.0.dev2.dist-info → flet_map-0.2.0.dev45.dist-info}/WHEEL +1 -1
  16. flet_map-0.2.0.dev45.dist-info/licenses/LICENSE +201 -0
  17. flutter/flet_map/CHANGELOG.md +4 -0
  18. flutter/flet_map/lib/flet_map.dart +1 -1
  19. flutter/flet_map/lib/src/circle_layer.dart +15 -25
  20. flutter/flet_map/lib/src/extension.dart +37 -0
  21. flutter/flet_map/lib/src/map.dart +93 -105
  22. flutter/flet_map/lib/src/marker_layer.dart +21 -33
  23. flutter/flet_map/lib/src/polygon_layer.dart +32 -52
  24. flutter/flet_map/lib/src/polyline_layer.dart +41 -64
  25. flutter/flet_map/lib/src/rich_attribution.dart +34 -34
  26. flutter/flet_map/lib/src/simple_attribution.dart +9 -23
  27. flutter/flet_map/lib/src/tile_layer.dart +47 -60
  28. flutter/flet_map/lib/src/utils/attribution_alignment.dart +1 -3
  29. flutter/flet_map/lib/src/utils/map.dart +257 -203
  30. flutter/flet_map/pubspec.lock +179 -130
  31. flutter/flet_map/pubspec.yaml +10 -5
  32. flet_map/text_source_attribution.py +0 -87
  33. flet_map-0.1.0.dev2.dist-info/METADATA +0 -168
  34. flet_map-0.1.0.dev2.dist-info/RECORD +0 -34
  35. flutter/flet_map/lib/src/create_control.dart +0 -70
  36. flutter/flet_map/lib/src/text_source_attribution.dart +0 -29
  37. {flet_map-0.1.0.dev2.dist-info → flet_map-0.2.0.dev45.dist-info}/top_level.txt +0 -0
flet_map/map.py CHANGED
@@ -1,674 +1,532 @@
1
- import json
2
- from dataclasses import dataclass
3
- from enum import Enum, EnumMeta, IntFlag
4
- from typing import Any, List, Optional, Tuple, Union
5
- from warnings import warn
6
-
7
- from flet.core.animation import AnimationCurve, AnimationValue
8
- from flet.core.badge import BadgeValue
9
- from flet.core.constrained_control import ConstrainedControl
10
- from flet.core.control import OptionalNumber
11
- from flet.core.event_handler import EventHandler
12
- from flet_map.map_layer import MapLayer
13
- from flet.core.ref import Ref
14
- from flet.core.tooltip import TooltipValue
15
- from flet.core.transform import Offset
16
- from flet.core.types import (
17
- ColorEnums,
18
- ColorValue,
19
- ControlEvent,
20
- DurationValue,
21
- Number,
22
- OffsetValue,
23
- OptionalControlEventCallable,
24
- OptionalEventCallable,
25
- ResponsiveNumber,
26
- RotateValue,
27
- ScaleValue,
1
+ import asyncio
2
+ from dataclasses import field
3
+ from typing import Optional
4
+
5
+ import flet as ft
6
+
7
+ from .map_layer import MapLayer
8
+ from .types import (
9
+ CameraFit,
10
+ InteractionConfiguration,
11
+ MapEvent,
12
+ MapHoverEvent,
13
+ MapLatitudeLongitude,
14
+ MapPointerEvent,
15
+ MapPositionChangeEvent,
16
+ MapTapEvent,
28
17
  )
29
18
 
19
+ __all__ = ["Map"]
30
20
 
31
- @dataclass
32
- class MapLatitudeLongitude:
33
- latitude: Union[float, int]
34
- longitude: Union[float, int]
35
-
36
-
37
- @dataclass
38
- class MapLatitudeLongitudeBounds:
39
- corner_1: MapLatitudeLongitude
40
- corner_2: MapLatitudeLongitude
41
-
42
-
43
- class MapInteractiveFlag(IntFlag):
44
- NONE = 0
45
- DRAG = 1 << 0
46
- FLING_ANIMATION = 1 << 1
47
- PINCH_MOVE = 1 << 2
48
- PINCH_ZOOM = 1 << 3
49
- DOUBLE_TAP_ZOOM = 1 << 4
50
- DOUBLE_TAP_DRAG_ZOOM = 1 << 5
51
- SCROLL_WHEEL_ZOOM = 1 << 6
52
- ROTATE = 1 << 7
53
- ALL = (
54
- (1 << 0)
55
- | (1 << 1)
56
- | (1 << 2)
57
- | (1 << 3)
58
- | (1 << 4)
59
- | (1 << 5)
60
- | (1 << 6)
61
- | (1 << 7)
21
+
22
+ @ft.control("Map")
23
+ class Map(ft.ConstrainedControl):
24
+ """
25
+ An interactive map control that allows displaying various layers.
26
+ """
27
+
28
+ layers: list[MapLayer]
29
+ """
30
+ A list of layers to be displayed (stack-like) on the map.
31
+
32
+ Value is of type [`MapLayer`][(p).].
33
+ """
34
+
35
+ initial_center: MapLatitudeLongitude = field(
36
+ default_factory=lambda: MapLatitudeLongitude(latitude=50.5, longitude=30.51)
62
37
  )
38
+ """
39
+ The initial center of the map.
63
40
 
41
+ Value is of type `MapLatitudeLongitude`.
42
+ """
64
43
 
65
- class MapMultiFingerGesture(IntFlag):
66
- NONE = 0
67
- PINCH_MOVE = 1 << 0
68
- PINCH_ZOOM = 1 << 1
69
- ROTATE = 1 << 2
70
- ALL = (1 << 0) | (1 << 1) | (1 << 2)
71
-
72
-
73
- class MapPointerDeviceTypeDeprecated(EnumMeta):
74
- def __getattribute__(self, item):
75
- if item in [
76
- "TOUCH",
77
- "MOUSE",
78
- "STYLUS",
79
- "INVERTED_STYLUS",
80
- "TRACKPAD",
81
- "UNKNOWN",
82
- ]:
83
- warn(
84
- "MapPointerDeviceType enum is deprecated since version 0.25.0 "
85
- "and will be removed in version 0.28.0. Use PointerDeviceType enum instead.",
86
- DeprecationWarning,
87
- stacklevel=2,
88
- )
89
- return EnumMeta.__getattribute__(self, item)
44
+ initial_rotation: ft.Number = 0.0
45
+ """
46
+ The rotation (in degrees) when the map is first loaded.
47
+ """
48
+
49
+ initial_zoom: ft.Number = 13.0
50
+ """
51
+ The zoom when the map is first loaded.
52
+ If initial_camera_fit is defined this has no effect.
53
+ """
54
+
55
+ interaction_configuration: InteractionConfiguration = field(
56
+ default_factory=lambda: InteractionConfiguration()
57
+ )
58
+ """
59
+ The interaction configuration.
60
+ """
61
+
62
+ bgcolor: ft.ColorValue = ft.Colors.GREY_300
63
+ """
64
+ The background color of this control.
65
+ """
66
+
67
+ keep_alive: bool = False
68
+ """
69
+ Whether to enable the built in keep-alive functionality.
70
+
71
+ If the map is within a complex layout, such as a `ListView`,
72
+ the map will reset to it's inital position after it appears back into view.
73
+ To ensure this doesn't happen, enable this flag to prevent it from rebuilding.
74
+ """
75
+
76
+ max_zoom: Optional[ft.Number] = None
77
+ """
78
+ The maximum (highest) zoom level of every layer.
79
+ Each layer can specify additional zoom level restrictions.
80
+ """
90
81
 
82
+ min_zoom: Optional[ft.Number] = None
83
+ """
84
+ The minimum (smallest) zoom level of every layer.
85
+ Each layer can specify additional zoom level restrictions.
86
+ """
91
87
 
92
- class MapPointerDeviceType(Enum, metaclass=MapPointerDeviceTypeDeprecated):
93
- TOUCH = "touch"
94
- MOUSE = "mouse"
95
- STYLUS = "stylus"
96
- INVERTED_STYLUS = "invertedStylus"
97
- TRACKPAD = "trackpad"
98
- UNKNOWN = "unknown"
88
+ animation_curve: ft.AnimationCurve = ft.AnimationCurve.FAST_OUT_SLOWIN
89
+ """
90
+ The default animation curve to be used for map-animations
91
+ when calling instance methods like `zoom_in()`, `rotate_from()`, `move_to()` etc.
92
+ """
99
93
 
94
+ animation_duration: ft.DurationValue = field(
95
+ default_factory=lambda: ft.Duration(milliseconds=500)
96
+ )
97
+ """
98
+ The default animation duration to be used for map-animations
99
+ when calling instance methods like `zoom_in()`, `rotate_from()`, `move_to()` etc.
100
+ """
100
101
 
101
- @dataclass
102
- class MapInteractionConfiguration:
103
- enable_multi_finger_gesture_race: Optional[bool] = None
104
- pinch_move_threshold: OptionalNumber = None
105
- scroll_wheel_velocity: OptionalNumber = None
106
- pinch_zoom_threshold: OptionalNumber = None
107
- rotation_threshold: OptionalNumber = None
108
- flags: Optional[MapInteractiveFlag] = None
109
- rotation_win_gestures: Optional[MapMultiFingerGesture] = None
110
- pinch_move_win_gestures: Optional[MapMultiFingerGesture] = None
111
- pinch_zoom_win_gestures: Optional[MapMultiFingerGesture] = None
102
+ initial_camera_fit: Optional[CameraFit] = None
103
+ """
104
+ Defines the visible bounds when the map is first loaded.
105
+ Takes precedence over `initial_center`/`initial_zoom`.
106
+ """
112
107
 
108
+ on_init: ft.OptionalControlEventHandler["Map"] = None
109
+ """
110
+ Fires when the map is initialized.
111
+ """
113
112
 
114
- class Map(ConstrainedControl):
113
+ on_tap: ft.OptionalEventHandler[MapTapEvent["Map"]] = None
115
114
  """
116
- Map Control.
115
+ Fires when a tap event occurs.
117
116
 
118
- -----
117
+ Event handler argument is of type [`MapTapEvent`][(p).].
118
+ """
119
119
 
120
- Online docs: https://flet.dev/docs/controls/map
120
+ on_hover: ft.OptionalEventHandler[MapHoverEvent["Map"]] = None
121
121
  """
122
+ Fires when a hover event occurs.
122
123
 
123
- def __init__(
124
- self,
125
- layers: List[MapLayer],
126
- initial_center: Optional[MapLatitudeLongitude] = None,
127
- initial_rotation: OptionalNumber = None,
128
- initial_zoom: OptionalNumber = None,
129
- interaction_configuration: Optional[MapInteractionConfiguration] = None,
130
- bgcolor: Optional[ColorValue] = None,
131
- keep_alive: Optional[bool] = None,
132
- max_zoom: OptionalNumber = None,
133
- min_zoom: OptionalNumber = None,
134
- animation_curve: Optional[AnimationCurve] = None,
135
- animation_duration: DurationValue = None,
136
- on_init: OptionalControlEventCallable = None,
137
- on_tap: OptionalEventCallable["MapTapEvent"] = None,
138
- on_hover: OptionalEventCallable["MapHoverEvent"] = None,
139
- on_secondary_tap: OptionalEventCallable["MapTapEvent"] = None,
140
- on_long_press: OptionalEventCallable["MapTapEvent"] = None,
141
- on_event: OptionalEventCallable["MapEvent"] = None,
142
- on_position_change: OptionalEventCallable["MapPositionChangeEvent"] = None,
143
- on_pointer_down: OptionalEventCallable["MapPointerEvent"] = None,
144
- on_pointer_cancel: OptionalEventCallable["MapPointerEvent"] = None,
145
- on_pointer_up: OptionalEventCallable["MapPointerEvent"] = None,
146
- #
147
- # ConstrainedControl
148
- #
149
- ref: Optional[Ref] = None,
150
- key: Optional[str] = None,
151
- width: OptionalNumber = None,
152
- height: OptionalNumber = None,
153
- left: OptionalNumber = None,
154
- top: OptionalNumber = None,
155
- right: OptionalNumber = None,
156
- bottom: OptionalNumber = None,
157
- expand: Union[None, bool, int] = None,
158
- expand_loose: Optional[bool] = None,
159
- col: Optional[ResponsiveNumber] = None,
160
- opacity: OptionalNumber = None,
161
- rotate: RotateValue = None,
162
- scale: ScaleValue = None,
163
- offset: OffsetValue = None,
164
- aspect_ratio: OptionalNumber = None,
165
- animate_opacity: Optional[AnimationValue] = None,
166
- animate_size: Optional[AnimationValue] = None,
167
- animate_position: Optional[AnimationValue] = None,
168
- animate_rotation: Optional[AnimationValue] = None,
169
- animate_scale: Optional[AnimationValue] = None,
170
- animate_offset: Optional[AnimationValue] = None,
171
- on_animation_end: OptionalControlEventCallable = None,
172
- tooltip: TooltipValue = None,
173
- badge: Optional[BadgeValue] = None,
174
- visible: Optional[bool] = None,
175
- disabled: Optional[bool] = None,
176
- data: Any = None,
177
- ):
178
- ConstrainedControl.__init__(
179
- self,
180
- ref=ref,
181
- key=key,
182
- width=width,
183
- height=height,
184
- left=left,
185
- top=top,
186
- right=right,
187
- bottom=bottom,
188
- expand=expand,
189
- expand_loose=expand_loose,
190
- col=col,
191
- opacity=opacity,
192
- rotate=rotate,
193
- scale=scale,
194
- offset=offset,
195
- aspect_ratio=aspect_ratio,
196
- animate_opacity=animate_opacity,
197
- animate_size=animate_size,
198
- animate_position=animate_position,
199
- animate_rotation=animate_rotation,
200
- animate_scale=animate_scale,
201
- animate_offset=animate_offset,
202
- on_animation_end=on_animation_end,
203
- tooltip=tooltip,
204
- badge=badge,
205
- visible=visible,
206
- disabled=disabled,
207
- data=data,
208
- )
209
- self.__on_tap = EventHandler(lambda e: MapTapEvent(e))
210
- self._add_event_handler("tap", self.__on_tap.get_handler())
124
+ Event handler argument is of type [`MapHoverEvent`][(p).].
125
+ """
211
126
 
212
- self.__on_hover = EventHandler(lambda e: MapHoverEvent(e))
213
- self._add_event_handler("hover", self.__on_hover.get_handler())
127
+ on_secondary_tap: ft.OptionalEventHandler[MapTapEvent["Map"]] = None
128
+ """
129
+ Fires when a secondary tap event occurs.
214
130
 
215
- self.__on_secondary_tap = EventHandler(lambda e: MapTapEvent(e))
216
- self._add_event_handler("secondary_tap", self.__on_secondary_tap.get_handler())
131
+ Event handler argument is of type [`MapTapEvent`][(p).].
132
+ """
217
133
 
218
- self.__on_long_press = EventHandler(lambda e: MapTapEvent(e))
219
- self._add_event_handler("long_press", self.__on_long_press.get_handler())
134
+ on_long_press: ft.OptionalEventHandler[MapTapEvent["Map"]] = None
135
+ """
136
+ Fires when a long press event occurs.
220
137
 
221
- self.__on_event = EventHandler(lambda e: MapEvent(e))
222
- self._add_event_handler("event", self.__on_event.get_handler())
138
+ Event handler argument is of type [`MapTapEvent`][(p).].
139
+ """
223
140
 
224
- self.__on_position_change = EventHandler(lambda e: MapPositionChangeEvent(e))
225
- self._add_event_handler(
226
- "position_change", self.__on_position_change.get_handler()
227
- )
141
+ on_event: ft.OptionalEventHandler[MapEvent["Map"]] = None
142
+ """
143
+ Fires when any map events occurs.
144
+
145
+ Event handler argument is of type [`MapEvent`][(p).].
146
+ """
228
147
 
229
- self.__on_pointer_down = EventHandler(lambda e: MapPointerEvent(e))
230
- self._add_event_handler("pointer_down", self.__on_pointer_down.get_handler())
148
+ on_position_change: ft.OptionalEventHandler[MapPositionChangeEvent["Map"]] = None
149
+ """
150
+ Fires when the map position changes.
231
151
 
232
- self.__on_pointer_cancel = EventHandler(lambda e: MapPointerEvent(e))
233
- self._add_event_handler(
234
- "pointer_cancel", self.__on_pointer_cancel.get_handler()
235
- )
152
+ Event handler argument is of type [`MapPositionChangeEvent`][(p).].
153
+ """
236
154
 
237
- self.__on_pointer_up = EventHandler(lambda e: MapPointerEvent(e))
238
- self._add_event_handler("pointer_up", self.__on_pointer_up.get_handler())
239
-
240
- self.layers = layers
241
- self.initial_center = initial_center
242
- self.initial_rotation = initial_rotation
243
- self.initial_zoom = initial_zoom
244
- self.interaction_configuration = interaction_configuration
245
- self.bgcolor = bgcolor
246
- self.keep_alive = keep_alive
247
- self.max_zoom = max_zoom
248
- self.min_zoom = min_zoom
249
- self.animation_curve = animation_curve
250
- self.animation_duration = animation_duration
251
- self.on_tap = on_tap
252
- self.on_hover = on_hover
253
- self.on_secondary_tap = on_secondary_tap
254
- self.on_init = on_init
255
- self.on_long_press = on_long_press
256
- self.on_event = on_event
257
- self.on_position_change = on_position_change
258
- self.on_pointer_down = on_pointer_down
259
- self.on_pointer_cancel = on_pointer_cancel
260
- self.on_pointer_up = on_pointer_up
261
-
262
- def before_update(self):
263
- self._set_attr_json("initialCenter", self.__initial_center)
264
- self._set_attr_json("animationDuration", self.__animation_duration)
265
- self._set_attr_json(
266
- "interactionConfiguration", self.__interaction_configuration
155
+ on_pointer_down: ft.OptionalEventHandler[MapPointerEvent["Map"]] = None
156
+ """
157
+ Fires when a pointer down event occurs.
158
+
159
+ Event handler argument is of type [`MapPointerEvent`][(p).].
160
+ """
161
+
162
+ on_pointer_cancel: ft.OptionalEventHandler[MapPointerEvent["Map"]] = None
163
+ """
164
+ Fires when a pointer cancel event occurs.
165
+
166
+ Event handler argument is of type [`MapPointerEvent`][(p).].
167
+ """
168
+
169
+ on_pointer_up: ft.OptionalEventHandler[MapPointerEvent["Map"]] = None
170
+ """
171
+ Fires when a pointer up event occurs.
172
+
173
+ Event handler argument is of type [`MapPointerEvent`][(p).].
174
+ """
175
+
176
+ async def rotate_from_async(
177
+ self,
178
+ degree: ft.Number,
179
+ animation_curve: Optional[ft.AnimationCurve] = None,
180
+ animation_duration: Optional[ft.DurationValue] = None,
181
+ cancel_ongoing_animations: bool = False,
182
+ ) -> None:
183
+ """
184
+ Applies a rotation of `degree` to the current rotation.
185
+
186
+ Args:
187
+ degree: The number of degrees to increment to the current rotation.
188
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
189
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
190
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
191
+ """
192
+ await self._invoke_method_async(
193
+ method_name="rotate_from",
194
+ arguments={
195
+ "degree": degree,
196
+ "curve": animation_curve or self.animation_curve,
197
+ "duration": animation_duration or self.animation_duration,
198
+ "cancel_ongoing_animations": cancel_ongoing_animations,
199
+ },
267
200
  )
268
201
 
269
202
  def rotate_from(
270
203
  self,
271
- degree: Number,
272
- animation_curve: Optional[AnimationCurve] = None,
273
- ):
274
- self.invoke_method(
275
- "rotate_from",
204
+ degree: ft.Number,
205
+ animation_curve: Optional[ft.AnimationCurve] = None,
206
+ animation_duration: Optional[ft.DurationValue] = None,
207
+ cancel_ongoing_animations: bool = False,
208
+ ) -> None:
209
+ """
210
+ Applies a rotation of `degree` to the current rotation.
211
+
212
+ Args:
213
+ degree: The number of degrees to increment to the current rotation.
214
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
215
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
216
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
217
+ """
218
+ asyncio.create_task(
219
+ self.rotate_from_async(
220
+ degree, animation_curve, animation_duration, cancel_ongoing_animations
221
+ )
222
+ )
223
+
224
+ async def reset_rotation_async(
225
+ self,
226
+ animation_curve: Optional[ft.AnimationCurve] = None,
227
+ animation_duration: Optional[ft.DurationValue] = None,
228
+ cancel_ongoing_animations: bool = False,
229
+ ) -> None:
230
+ """
231
+ Resets the map's rotation to 0 degrees.
232
+
233
+ Args:
234
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
235
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
236
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
237
+ """
238
+ await self._invoke_method_async(
239
+ method_name="reset_rotation",
276
240
  arguments={
277
- "degree": degree,
278
- "curve": animation_curve.value if animation_curve else None,
241
+ "curve": animation_curve or self.animation_curve,
242
+ "duration": animation_duration or self.animation_duration,
243
+ "cancel_ongoing_animations": cancel_ongoing_animations,
279
244
  },
280
245
  )
281
246
 
282
247
  def reset_rotation(
283
248
  self,
284
- animation_curve: Optional[AnimationCurve] = None,
285
- animation_duration: DurationValue = None,
286
- ):
287
- self.invoke_method(
288
- "reset_rotation",
249
+ animation_curve: Optional[ft.AnimationCurve] = None,
250
+ animation_duration: ft.DurationValue = None,
251
+ cancel_ongoing_animations: bool = False,
252
+ ) -> None:
253
+ """
254
+ Resets the map's rotation to 0 degrees.
255
+
256
+ Args:
257
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
258
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
259
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
260
+ """
261
+ asyncio.create_task(
262
+ self.reset_rotation_async(
263
+ animation_curve, animation_duration, cancel_ongoing_animations
264
+ )
265
+ )
266
+
267
+ async def zoom_in_async(
268
+ self,
269
+ animation_curve: Optional[ft.AnimationCurve] = None,
270
+ animation_duration: Optional[ft.DurationValue] = None,
271
+ cancel_ongoing_animations: bool = False,
272
+ ) -> None:
273
+ """
274
+ Zooms in by one zoom-level from the current one.
275
+
276
+ Args:
277
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
278
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
279
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
280
+ """
281
+ await self._invoke_method_async(
282
+ method_name="zoom_in",
289
283
  arguments={
290
- "curve": animation_curve.value if animation_curve else None,
291
- "duration": self._convert_attr_json(animation_duration),
284
+ "curve": animation_curve or self.animation_curve,
285
+ "duration": animation_duration or self.animation_duration,
286
+ "cancel_ongoing_animations": cancel_ongoing_animations,
292
287
  },
293
288
  )
294
289
 
295
290
  def zoom_in(
296
291
  self,
297
- animation_curve: Optional[AnimationCurve] = None,
298
- animation_duration: DurationValue = None,
299
- ):
300
- self.invoke_method(
301
- "zoom_in",
292
+ animation_curve: Optional[ft.AnimationCurve] = None,
293
+ animation_duration: Optional[ft.DurationValue] = None,
294
+ cancel_ongoing_animations: bool = False,
295
+ ) -> None:
296
+ """
297
+ Zooms in by one zoom-level from the current one.
298
+
299
+ Args:
300
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
301
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
302
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
303
+ """
304
+ asyncio.create_task(
305
+ self.zoom_in_async(
306
+ animation_curve, animation_duration, cancel_ongoing_animations
307
+ )
308
+ )
309
+
310
+ async def zoom_out_async(
311
+ self,
312
+ animation_curve: Optional[ft.AnimationCurve] = None,
313
+ animation_duration: Optional[ft.DurationValue] = None,
314
+ cancel_ongoing_animations: bool = False,
315
+ ) -> None:
316
+ """
317
+ Zooms out by one zoom-level from the current one.
318
+
319
+ Args:
320
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
321
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
322
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
323
+ """
324
+ await self._invoke_method_async(
325
+ method_name="zoom_out",
302
326
  arguments={
303
- "curve": animation_curve.value if animation_curve else None,
304
- "duration": self._convert_attr_json(animation_duration),
327
+ "curve": animation_curve or self.animation_curve,
328
+ "duration": animation_duration or self.animation_duration,
329
+ "cancel_ongoing_animations": cancel_ongoing_animations,
305
330
  },
306
331
  )
307
332
 
308
333
  def zoom_out(
309
334
  self,
310
- animation_curve: Optional[AnimationCurve] = None,
311
- animation_duration: DurationValue = None,
312
- ):
313
- self.invoke_method(
314
- "zoom_out",
335
+ animation_curve: Optional[ft.AnimationCurve] = None,
336
+ animation_duration: Optional[ft.DurationValue] = None,
337
+ cancel_ongoing_animations: bool = False,
338
+ ) -> None:
339
+ """
340
+ Zooms out by one zoom-level from the current one.
341
+
342
+ Args:
343
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
344
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
345
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
346
+ """
347
+ asyncio.create_task(
348
+ self.zoom_out_async(
349
+ animation_curve, animation_duration, cancel_ongoing_animations
350
+ )
351
+ )
352
+
353
+ async def zoom_to_async(
354
+ self,
355
+ zoom: ft.Number,
356
+ animation_curve: Optional[ft.AnimationCurve] = None,
357
+ animation_duration: Optional[ft.DurationValue] = None,
358
+ cancel_ongoing_animations: bool = False,
359
+ ) -> None:
360
+ """
361
+ Zoom the map to a specific zoom level.
362
+
363
+ Args:
364
+ zoom: The zoom level to zoom to.
365
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
366
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
367
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
368
+ """
369
+ await self._invoke_method_async(
370
+ method_name="zoom_to",
315
371
  arguments={
316
- "curve": animation_curve.value if animation_curve else None,
317
- "duration": self._convert_attr_json(animation_duration),
372
+ "zoom": zoom,
373
+ "curve": animation_curve or self.animation_curve,
374
+ "duration": animation_duration or self.animation_duration,
375
+ "cancel_ongoing_animations": cancel_ongoing_animations,
318
376
  },
319
377
  )
320
378
 
321
379
  def zoom_to(
322
380
  self,
323
- zoom: Number,
324
- animation_curve: Optional[AnimationCurve] = None,
325
- animation_duration: DurationValue = None,
326
- ):
327
- self.invoke_method(
328
- "zoom_to",
381
+ zoom: ft.Number,
382
+ animation_curve: Optional[ft.AnimationCurve] = None,
383
+ animation_duration: Optional[ft.DurationValue] = None,
384
+ cancel_ongoing_animations: bool = False,
385
+ ) -> None:
386
+ """
387
+ Zoom the map to a specific zoom level.
388
+
389
+ Args:
390
+ zoom: The zoom level to zoom to.
391
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
392
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
393
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
394
+ """
395
+ asyncio.create_task(
396
+ self.zoom_to_async(
397
+ zoom, animation_curve, animation_duration, cancel_ongoing_animations
398
+ )
399
+ )
400
+
401
+ async def move_to_async(
402
+ self,
403
+ destination: Optional[MapLatitudeLongitude] = None,
404
+ zoom: Optional[ft.Number] = None,
405
+ rotation: Optional[ft.Number] = None,
406
+ animation_curve: Optional[ft.AnimationCurve] = None,
407
+ animation_duration: Optional[ft.DurationValue] = None,
408
+ offset: ft.OffsetValue = ft.Offset(0, 0),
409
+ cancel_ongoing_animations: bool = False,
410
+ ) -> None:
411
+ """
412
+ Moves to a specific location.
413
+
414
+ Args:
415
+ destination: The destination point to move to.
416
+ zoom: The zoom level to be applied. If provided, must be greater than or equal to `0.0`.
417
+ rotation: Rotation (in degrees) to be applied.
418
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
419
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
420
+ offset: The offset to be used. Only works when `rotation` is `None`.
421
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
422
+
423
+ Raises:
424
+ AssertionError: If `zoom` is not `None` and is negative.
425
+ """
426
+ assert zoom is None or zoom >= 0, "zoom must be greater than or equal to zero"
427
+ await self._invoke_method_async(
428
+ method_name="move_to",
329
429
  arguments={
430
+ "destination": destination,
330
431
  "zoom": zoom,
331
- "curve": animation_curve.value if animation_curve else None,
332
- "duration": self._convert_attr_json(animation_duration),
432
+ "offset": offset,
433
+ "rotation": rotation,
434
+ "curve": animation_curve or self.animation_curve,
435
+ "duration": animation_duration or self.animation_duration,
436
+ "cancel_ongoing_animations": cancel_ongoing_animations,
333
437
  },
334
438
  )
335
439
 
336
440
  def move_to(
337
441
  self,
338
442
  destination: Optional[MapLatitudeLongitude] = None,
339
- zoom: OptionalNumber = None,
340
- rotation: OptionalNumber = None,
341
- animation_curve: Optional[AnimationCurve] = None,
342
- animation_duration: DurationValue = None,
343
- offset: Optional[Union[Offset, Tuple[Union[Number], Union[Number]]]] = None,
344
- ):
345
- if isinstance(offset, tuple):
346
- offset = Offset(offset[0], offset[1])
347
- self.invoke_method(
348
- "move_to",
349
- arguments={
350
- "lat": str(destination.latitude) if destination else None,
351
- "long": str(destination.longitude) if destination else None,
352
- "zoom": zoom,
353
- "ox": str(offset.x) if offset else None,
354
- "oy": str(offset.y) if offset else None,
355
- "rot": rotation,
356
- "curve": animation_curve.value if animation_curve else None,
357
- "duration": self._convert_attr_json(animation_duration),
358
- },
443
+ zoom: Optional[ft.Number] = None,
444
+ rotation: Optional[ft.Number] = None,
445
+ animation_curve: Optional[ft.AnimationCurve] = None,
446
+ animation_duration: Optional[ft.DurationValue] = None,
447
+ offset: ft.OffsetValue = ft.Offset(0, 0),
448
+ cancel_ongoing_animations: bool = False,
449
+ ) -> None:
450
+ """
451
+ Moves to a specific location.
452
+
453
+ Args:
454
+ destination: The destination point to move to.
455
+ zoom: The zoom level to be applied. If provided, must be greater than or equal to `0.0`.
456
+ rotation: Rotation (in degrees) to be applied.
457
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
458
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
459
+ offset: The offset to be used. Only works when `rotation` is `None`.
460
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
461
+
462
+ Raises:
463
+ AssertionError: If `zoom` is not `None` and is negative.
464
+ """
465
+ asyncio.create_task(
466
+ self.move_to_async(
467
+ destination,
468
+ zoom,
469
+ rotation,
470
+ animation_curve,
471
+ animation_duration,
472
+ offset,
473
+ cancel_ongoing_animations,
474
+ )
359
475
  )
360
476
 
361
- def center_on(
477
+ async def center_on_async(
362
478
  self,
363
- point: Optional[MapLatitudeLongitude],
364
- zoom: OptionalNumber,
365
- animation_curve: Optional[AnimationCurve] = None,
366
- animation_duration: DurationValue = None,
367
- ):
368
- self.invoke_method(
369
- "center_on",
479
+ point: MapLatitudeLongitude,
480
+ zoom: Optional[ft.Number],
481
+ animation_curve: Optional[ft.AnimationCurve] = None,
482
+ animation_duration: Optional[ft.DurationValue] = None,
483
+ cancel_ongoing_animations: bool = False,
484
+ ) -> None:
485
+ """
486
+ Centers the map on the given point.
487
+
488
+ Args:
489
+ point: The point on which to center the map.
490
+ zoom: The zoom level to be applied.
491
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
492
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
493
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
494
+ """
495
+ await self._invoke_method_async(
496
+ method_name="center_on",
370
497
  arguments={
371
- "lat": str(point.latitude) if point else None,
372
- "long": str(point.longitude) if point else None,
498
+ "point": point,
373
499
  "zoom": zoom,
374
- "curve": animation_curve.value if animation_curve else None,
375
- "duration": self._convert_attr_json(animation_duration),
500
+ "curve": animation_curve or self.animation_curve,
501
+ "duration": animation_duration or self.animation_duration,
502
+ "cancel_ongoing_animations": cancel_ongoing_animations,
376
503
  },
377
504
  )
378
505
 
379
- def _get_control_name(self):
380
- return "map"
381
-
382
- def _get_children(self):
383
- return self.__layers
384
-
385
- # layers
386
- @property
387
- def layers(self) -> List[MapLayer]:
388
- return self.__layers
389
-
390
- @layers.setter
391
- def layers(self, value: List[MapLayer]):
392
- self.__layers = value
393
-
394
- # initial_center
395
- @property
396
- def initial_center(self) -> Optional[MapLatitudeLongitude]:
397
- return self.__initial_center
398
-
399
- @initial_center.setter
400
- def initial_center(self, value: Optional[MapLatitudeLongitude]):
401
- self.__initial_center = value
402
-
403
- # initial_rotation
404
- @property
405
- def initial_rotation(self) -> OptionalNumber:
406
- return self._get_attr("initialRotation", data_type="float")
407
-
408
- @initial_rotation.setter
409
- def initial_rotation(self, value: OptionalNumber):
410
- self._set_attr("initialRotation", value)
411
-
412
- # initial_zoom
413
- @property
414
- def initial_zoom(self) -> OptionalNumber:
415
- return self._get_attr("initialZoom", data_type="float")
416
-
417
- @initial_zoom.setter
418
- def initial_zoom(self, value: OptionalNumber):
419
- self._set_attr("initialZoom", value)
420
-
421
- # interaction_configuration
422
- @property
423
- def interaction_configuration(self) -> Optional[MapInteractionConfiguration]:
424
- return self.__interaction_configuration
425
-
426
- @interaction_configuration.setter
427
- def interaction_configuration(self, value: Optional[MapInteractionConfiguration]):
428
- self.__interaction_configuration = value
429
-
430
- # bgcolor
431
- @property
432
- def bgcolor(self) -> Optional[ColorValue]:
433
- return self.__bgcolor
434
-
435
- @bgcolor.setter
436
- def bgcolor(self, value: Optional[ColorValue]):
437
- self.__bgcolor = value
438
- self._set_enum_attr("bgcolor", value, ColorEnums)
439
-
440
- # keep_alive
441
- @property
442
- def keep_alive(self) -> Optional[bool]:
443
- return self._get_attr("keepAlive", data_type="bool")
444
-
445
- @keep_alive.setter
446
- def keep_alive(self, value: Optional[bool]):
447
- self._set_attr("keepAlive", value)
448
-
449
- # max_zoom
450
- @property
451
- def max_zoom(self) -> OptionalNumber:
452
- return self._get_attr("maxZoom", data_type="float")
453
-
454
- @max_zoom.setter
455
- def max_zoom(self, value: OptionalNumber):
456
- self._set_attr("maxZoom", value)
457
-
458
- # min_zoom
459
- @property
460
- def min_zoom(self) -> OptionalNumber:
461
- return self._get_attr("minZoom", data_type="float")
462
-
463
- @min_zoom.setter
464
- def min_zoom(self, value: OptionalNumber):
465
- self._set_attr("minZoom", value)
466
-
467
- # animation_curve
468
- @property
469
- def animation_curve(self) -> Optional[AnimationCurve]:
470
- return self.__animation_curve
471
-
472
- @animation_curve.setter
473
- def animation_curve(self, value: Optional[AnimationCurve]):
474
- self.__animation_curve = value
475
- self._set_enum_attr("animationCurve", value, AnimationCurve)
476
-
477
- # animation_duration
478
- @property
479
- def animation_duration(self) -> Optional[DurationValue]:
480
- return self.__animation_duration
481
-
482
- @animation_duration.setter
483
- def animation_duration(self, value: Optional[DurationValue]):
484
- self.__animation_duration = value
485
-
486
- # on_tap
487
- @property
488
- def on_tap(self) -> OptionalEventCallable["MapTapEvent"]:
489
- return self.__on_tap.handler
490
-
491
- @on_tap.setter
492
- def on_tap(self, handler: OptionalEventCallable["MapTapEvent"]):
493
- self.__on_tap.handler = handler
494
- self._set_attr("onTap", True if handler is not None else None)
495
-
496
- # on_hover
497
- @property
498
- def on_hover(self) -> OptionalEventCallable["MapHoverEvent"]:
499
- return self.__on_hover.handler
500
-
501
- @on_hover.setter
502
- def on_hover(self, handler: OptionalEventCallable["MapHoverEvent"]):
503
- self.__on_hover.handler = handler
504
- self._set_attr("onHover", True if handler is not None else None)
505
-
506
- # on_secondary_tap
507
- @property
508
- def on_secondary_tap(self) -> OptionalEventCallable["MapTapEvent"]:
509
- return self.__on_secondary_tap.handler
510
-
511
- @on_secondary_tap.setter
512
- def on_secondary_tap(self, handler: OptionalEventCallable["MapTapEvent"]):
513
- self.__on_secondary_tap.handler = handler
514
- self._set_attr("onSecondaryTap", True if handler is not None else None)
515
-
516
- # on_long_press
517
- @property
518
- def on_long_press(self) -> OptionalEventCallable["MapTapEvent"]:
519
- return self.__on_long_press.handler
520
-
521
- @on_long_press.setter
522
- def on_long_press(self, handler: OptionalEventCallable["MapTapEvent"]):
523
- self.__on_long_press.handler = handler
524
- self._set_attr("onLongPress", True if handler is not None else None)
525
-
526
- # on_event
527
- @property
528
- def on_event(self) -> OptionalEventCallable["MapEvent"]:
529
- return self.__on_event.handler
530
-
531
- @on_event.setter
532
- def on_event(self, handler: OptionalEventCallable["MapEvent"]):
533
- self.__on_event.handler = handler
534
- self._set_attr("onEvent", True if handler is not None else None)
535
-
536
- # on_init
537
- @property
538
- def on_init(self) -> OptionalControlEventCallable:
539
- return self._get_event_handler("init")
540
-
541
- @on_init.setter
542
- def on_init(self, handler: OptionalControlEventCallable):
543
- self._add_event_handler("init", handler)
544
- self._set_attr("onInit", True if handler is not None else None)
545
-
546
- # on_position_change
547
- @property
548
- def on_position_change(self) -> OptionalEventCallable["MapPositionChangeEvent"]:
549
- return self.__on_position_change.handler
550
-
551
- @on_position_change.setter
552
- def on_position_change(
553
- self, handler: OptionalEventCallable["MapPositionChangeEvent"]
554
- ):
555
- self.__on_position_change.handler = handler
556
- self._set_attr("onPositionChange", True if handler is not None else None)
557
-
558
- # on_pointer_down
559
- @property
560
- def on_pointer_down(self) -> OptionalEventCallable["MapPointerEvent"]:
561
- return self.__on_pointer_down.handler
562
-
563
- @on_pointer_down.setter
564
- def on_pointer_down(self, handler: OptionalEventCallable["MapPointerEvent"]):
565
- self.__on_pointer_down.handler = handler
566
- self._set_attr("onPointerDown", True if handler is not None else None)
567
-
568
- # on_pointer_cancel
569
- @property
570
- def on_pointer_cancel(self) -> OptionalEventCallable["MapPointerEvent"]:
571
- return self.__on_pointer_cancel.handler
572
-
573
- @on_pointer_cancel.setter
574
- def on_pointer_cancel(self, handler: OptionalEventCallable["MapPointerEvent"]):
575
- self.__on_pointer_cancel.handler = handler
576
- self._set_attr("onPointerCancel", True if handler is not None else None)
577
-
578
- # on_pointer_up
579
- @property
580
- def on_pointer_up(self) -> OptionalEventCallable["MapPointerEvent"]:
581
- return self.__on_pointer_up.handler
582
-
583
- @on_pointer_up.setter
584
- def on_pointer_up(self, handler: OptionalEventCallable["MapPointerEvent"]):
585
- self.__on_pointer_up.handler = handler
586
- self._set_attr("onPointerUp", True if handler is not None else None)
587
-
588
-
589
- class MapEventSource(Enum):
590
- MAP_CONTROLLER = "mapController"
591
- TAP = "tap"
592
- SECONDARY_TAP = "secondaryTap"
593
- LONG_PRESS = "longPress"
594
- DOUBLE_TAP = "doubleTap"
595
- DOUBLE_TAP_HOLD = "doubleTapHold"
596
- DRAG_START = "dragStart"
597
- ON_DRAG = "onDrag"
598
- DRAG_END = "dragEnd"
599
- MULTI_FINGER_GESTURE_START = "multiFingerGestureStart"
600
- ON_MULTI_FINGER = "onMultiFinger"
601
- MULTI_FINGER_GESTURE_END = "multiFingerEnd"
602
- FLING_ANIMATION_CONTROLLER = "flingAnimationController"
603
- DOUBLE_TAP_ZOOM_ANIMATION_CONTROLLER = "doubleTapZoomAnimationController"
604
- INTERACTIVE_FLAGS_CHANGED = "interactiveFlagsChanged"
605
- FIT_CAMERA = "fitCamera"
606
- CUSTOM = "custom"
607
- SCROLL_WHEEL = "scrollWheel"
608
- NON_ROTATED_SIZE_CHANGE = "nonRotatedSizeChange"
609
- CURSOR_KEYBOARD_ROTATION = "cursorKeyboardRotation"
610
-
611
-
612
- class MapTapEvent(ControlEvent):
613
- def __init__(self, e: ControlEvent) -> None:
614
- super().__init__(e.target, e.name, e.data, e.control, e.page)
615
- d = json.loads(e.data)
616
- self.local_x: Optional[float] = d.get("lx")
617
- self.local_y: Optional[float] = d.get("ly")
618
- self.global_x: float = d.get("gx")
619
- self.global_y: float = d.get("gy")
620
- self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
621
- d.get("lat"), d.get("long")
622
- )
623
-
624
-
625
- class MapHoverEvent(ControlEvent):
626
- def __init__(self, e: ControlEvent) -> None:
627
- super().__init__(e.target, e.name, e.data, e.control, e.page)
628
- d = json.loads(e.data)
629
- self.local_x: Optional[float] = d.get("lx")
630
- self.local_y: Optional[float] = d.get("ly")
631
- self.global_x: float = d.get("gx")
632
- self.global_y: float = d.get("gy")
633
- self.device_type: MapPointerDeviceType = MapPointerDeviceType(d.get("kind"))
634
- self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
635
- d.get("lat"), d.get("long")
636
- )
637
-
638
-
639
- class MapPositionChangeEvent(ControlEvent):
640
- def __init__(self, e: ControlEvent) -> None:
641
- super().__init__(e.target, e.name, e.data, e.control, e.page)
642
- d = json.loads(e.data)
643
- self.min_zoom: Optional[float] = d.get("min_zoom")
644
- self.max_zoom: Optional[float] = d.get("max_zoom")
645
- self.rotation: float = d.get("rot")
646
- self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
647
- d.get("lat"), d.get("long")
648
- )
649
-
650
-
651
- class MapPointerEvent(ControlEvent):
652
- def __init__(self, e: ControlEvent) -> None:
653
- super().__init__(e.target, e.name, e.data, e.control, e.page)
654
- d = json.loads(e.data)
655
- self.device_type: MapPointerDeviceType = MapPointerDeviceType(d.get("kind"))
656
- self.global_y: float = d.get("gy")
657
- self.global_x: float = d.get("gx")
658
- self.coordinates: MapLatitudeLongitude = MapLatitudeLongitude(
659
- d.get("lat"), d.get("long")
660
- )
661
-
662
-
663
- class MapEvent(ControlEvent):
664
- def __init__(self, e: ControlEvent) -> None:
665
- super().__init__(e.target, e.name, e.data, e.control, e.page)
666
- d = json.loads(e.data)
667
- self.source: MapEventSource = MapEventSource(d.get("src"))
668
- self.center: MapLatitudeLongitude = MapLatitudeLongitude(
669
- d.get("c_lat"), d.get("c_long")
506
+ def center_on(
507
+ self,
508
+ point: Optional[MapLatitudeLongitude],
509
+ zoom: Optional[ft.Number],
510
+ animation_curve: Optional[ft.AnimationCurve] = None,
511
+ animation_duration: Optional[ft.DurationValue] = None,
512
+ cancel_ongoing_animations: bool = False,
513
+ ) -> None:
514
+ """
515
+ Centers the map on the given point.
516
+
517
+ Args:
518
+ point: The point on which to center the map.
519
+ zoom: The zoom level to be applied.
520
+ animation_curve: The curve of the animation. If None (the default), `Map.animation_curve` will be used.
521
+ animation_duration: The duration of the animation. If None (the default), `Map.animation_duration` will be used.
522
+ cancel_ongoing_animations: Whether to cancel/stop all ongoing map-animations before starting this new one.
523
+ """
524
+ asyncio.create_task(
525
+ self.center_on_async(
526
+ point,
527
+ zoom,
528
+ animation_curve,
529
+ animation_duration,
530
+ cancel_ongoing_animations,
531
+ )
670
532
  )
671
- self.zoom: float = d.get("zoom")
672
- self.min_zoom: float = d.get("min_zoom")
673
- self.max_zoom: float = d.get("max_zoom")
674
- self.rotation: float = d.get("rot")