1+ package com.smarttoolfactory.image.zoom
2+
3+ import androidx.compose.animation.core.Animatable
4+ import androidx.compose.animation.core.VectorConverter
5+ import androidx.compose.runtime.Composable
6+ import androidx.compose.runtime.remember
7+ import androidx.compose.ui.geometry.Offset
8+ import kotlinx.coroutines.coroutineScope
9+
10+ @Composable
11+ fun rememberZoomState (
12+ initialZoom : Float = 1f,
13+ initialRotation : Float = 0f,
14+ minZoom : Float = 1f,
15+ maxZoom : Float = 5f
16+ ): ZoomState {
17+ return remember {
18+ ZoomState (
19+ initialZoom = initialZoom,
20+ initialRotation = initialRotation,
21+ minZoom = minZoom,
22+ maxZoom = maxZoom
23+ )
24+ }
25+ }
26+
27+ class ZoomState internal constructor(
28+ initialZoom : Float = 1f ,
29+ initialRotation : Float = 0f ,
30+ minZoom : Float = 1f ,
31+ maxZoom : Float = 5f
32+ ) {
33+ internal var zoomLevel = ZoomLevel .Min
34+
35+ internal val zoomMin = minZoom.coerceAtLeast(.5f )
36+ internal val zoomMax = maxZoom.coerceAtLeast(1f )
37+ internal val zoomInitial = initialZoom.coerceIn(zoomMin, zoomMax)
38+ internal val rotationInitial = initialRotation % 360
39+
40+ internal val animatablePan = Animatable (Offset .Zero , Offset .VectorConverter )
41+ internal val animatableZoom = Animatable (zoomInitial)
42+ internal val animatableRotation = Animatable (rotationInitial)
43+
44+ init {
45+ require(zoomMax >= zoomMin)
46+ }
47+
48+ val pan: Offset
49+ get() = animatablePan.value
50+
51+ val zoom: Float
52+ get() = animatableZoom.value
53+
54+ val rotation: Float
55+ get() = animatableRotation.value
56+
57+ val zoomData: ZoomData
58+ get() = ZoomData (
59+ zoom = animatableZoom.value,
60+ pan = animatablePan.value,
61+ rotation = animatableRotation.value
62+ )
63+
64+
65+ fun boundPan (maxX : Float , maxY : Float ) {
66+ animatablePan.updateBounds(
67+ Offset (- maxX, - maxY),
68+ Offset (maxX, maxY)
69+ )
70+ }
71+
72+ suspend fun animatePanTo (pan : Offset ) = coroutineScope {
73+ animatablePan.animateTo(pan)
74+ }
75+
76+ suspend fun animateZoomTo (zoom : Float ) = coroutineScope {
77+ animatableZoom.animateTo(zoom)
78+ }
79+
80+ suspend fun animateRotationTo (rotation : Float ) = coroutineScope {
81+ animatableRotation.animateTo(rotation)
82+ }
83+
84+ suspend fun snapPanTo (offset : Offset ) = coroutineScope {
85+ animatablePan.snapTo(offset)
86+ }
87+
88+ suspend fun snapZoomTo (zoom : Float ) = coroutineScope {
89+ animatableZoom.snapTo(zoom)
90+ }
91+
92+ suspend fun snapRotationTo (rotation : Float ) = coroutineScope {
93+ animatableRotation.snapTo(rotation)
94+ }
95+ }
0 commit comments