11package com.commandiron.compose_loading
22
3+ import androidx.compose.animation.core.*
4+ import androidx.compose.foundation.Canvas
35import androidx.compose.foundation.layout.Box
4- import androidx.compose.foundation.shape.CircleShape
6+ import androidx.compose.foundation.layout.size
57import androidx.compose.material3.MaterialTheme
6- import androidx.compose.material3.Text
78import androidx.compose.runtime.Composable
89import androidx.compose.ui.Alignment
910import androidx.compose.ui.Modifier
11+ import androidx.compose.ui.geometry.Offset
1012import androidx.compose.ui.graphics.Color
11- import androidx.compose.ui.graphics.Shape
12- import androidx.compose.ui.text.style.TextAlign
1313import androidx.compose.ui.unit.Dp
1414import androidx.compose.ui.unit.dp
15+ import com.commandiron.compose_loading.transition.EaseInOut
16+ import com.commandiron.compose_loading.transition.fractionTransition
17+ import kotlin.math.cos
18+ import kotlin.math.sin
1519
1620@Composable
1721fun Circle (
1822 modifier : Modifier = Modifier ,
19- size : Dp = 30.dp,
20- durationMillis : Int = 1400,
21- delayMillis : Int = 0,
23+ size : Dp = 24.dp,
24+ durationMillis : Int = 1200,
2225 color : Color = MaterialTheme .colorScheme.primary,
23- shape : Shape = CircleShape ,
26+ circleSizeRatio : Float = 1.0f
2427) {
28+ val transition = rememberInfiniteTransition()
29+
30+ val durationPerFraction = durationMillis / 2
31+
32+ val circleSizeMultiplier1 = transition.fractionTransition(
33+ initialValue = 0f ,
34+ targetValue = 1f ,
35+ durationMillis = durationPerFraction,
36+ offsetMillis = durationPerFraction / 6 * 1 ,
37+ repeatMode = RepeatMode .Reverse ,
38+ easing = EaseInOut
39+ )
40+ val circleSizeMultiplier2 = transition.fractionTransition(
41+ initialValue = 0f ,
42+ targetValue = 1f ,
43+ durationMillis = durationPerFraction,
44+ offsetMillis = durationPerFraction / 6 * 2 ,
45+ repeatMode = RepeatMode .Reverse ,
46+ easing = EaseInOut
47+ )
48+ val circleSizeMultiplier3 = transition.fractionTransition(
49+ initialValue = 0f ,
50+ targetValue = 1f ,
51+ durationMillis = durationPerFraction,
52+ offsetMillis = durationPerFraction / 6 * 3 ,
53+ repeatMode = RepeatMode .Reverse ,
54+ easing = EaseInOut
55+ )
56+ val circleSizeMultiplier4 = transition.fractionTransition(
57+ initialValue = 0f ,
58+ targetValue = 1f ,
59+ durationMillis = durationPerFraction,
60+ offsetMillis = durationPerFraction / 6 * 4 ,
61+ repeatMode = RepeatMode .Reverse ,
62+ easing = EaseInOut
63+ )
64+ val circleSizeMultiplier5 = transition.fractionTransition(
65+ initialValue = 0f ,
66+ targetValue = 1f ,
67+ durationMillis = durationPerFraction,
68+ offsetMillis = durationPerFraction / 6 * 5 ,
69+ repeatMode = RepeatMode .Reverse ,
70+ easing = EaseInOut
71+ )
72+ val circleSizeMultiplier6 = transition.fractionTransition(
73+ initialValue = 0f ,
74+ targetValue = 1f ,
75+ durationMillis = durationPerFraction,
76+ offsetMillis = durationPerFraction / 6 * 6 ,
77+ repeatMode = RepeatMode .Reverse ,
78+ easing = EaseInOut
79+ )
80+ val circleSizeMultiplier7 = transition.fractionTransition(
81+ initialValue = 0f ,
82+ targetValue = 1f ,
83+ durationMillis = durationMillis / 2 ,
84+ offsetMillis = durationPerFraction / 6 * 7 ,
85+ repeatMode = RepeatMode .Reverse ,
86+ easing = EaseInOut
87+ )
88+ val circleSizeMultiplier8 = transition.fractionTransition(
89+ initialValue = 0f ,
90+ targetValue = 1f ,
91+ durationMillis = durationMillis / 2 ,
92+ offsetMillis = durationPerFraction / 6 * 8 ,
93+ repeatMode = RepeatMode .Reverse ,
94+ easing = EaseInOut
95+ )
96+ val circleSizeMultiplier9 = transition.fractionTransition(
97+ initialValue = 0f ,
98+ targetValue = 1f ,
99+ durationMillis = durationMillis / 2 ,
100+ offsetMillis = durationPerFraction / 6 * 9 ,
101+ repeatMode = RepeatMode .Reverse ,
102+ easing = EaseInOut
103+ )
104+ val circleSizeMultiplier10 = transition.fractionTransition(
105+ initialValue = 0f ,
106+ targetValue = 1f ,
107+ durationMillis = durationMillis / 2 ,
108+ offsetMillis = durationPerFraction / 6 * 10 ,
109+ repeatMode = RepeatMode .Reverse ,
110+ easing = EaseInOut
111+ )
112+ val circleSizeMultiplier11 = transition.fractionTransition(
113+ initialValue = 0f ,
114+ targetValue = 1f ,
115+ durationMillis = durationMillis / 2 ,
116+ offsetMillis = durationPerFraction / 6 * 11 ,
117+ repeatMode = RepeatMode .Reverse ,
118+ easing = EaseInOut
119+ )
120+ val circleSizeMultiplier12 = transition.fractionTransition(
121+ initialValue = 0f ,
122+ targetValue = 1f ,
123+ durationMillis = durationMillis / 2 ,
124+ offsetMillis = durationPerFraction / 6 * 12 ,
125+ repeatMode = RepeatMode .Reverse ,
126+ easing = EaseInOut
127+ )
128+
25129 Box (
26130 modifier = modifier,
27131 contentAlignment = Alignment .Center
28132 ){
29- Text (
30- text = " Circle" ,
31- style = MaterialTheme .typography.labelSmall,
32- textAlign = TextAlign .Center
33- )
133+ Canvas (modifier = Modifier .size(size)){
134+ val pathRadius = (this .size.height / 2 )
135+ val radius1 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier1.value
136+ val radius2 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier2.value
137+ val radius3 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier3.value
138+ val radius4 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier4.value
139+ val radius5 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier5.value
140+ val radius6 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier6.value
141+ val radius7 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier7.value
142+ val radius8 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier8.value
143+ val radius9 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier9.value
144+ val radius10 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier10.value
145+ val radius11 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier11.value
146+ val radius12 = this .size.height / 12 * circleSizeRatio * circleSizeMultiplier12.value
147+
148+ for (i in 0 until 12 ){
149+ val angle = i / 12 .toDouble() * 360.0
150+ val offsetX = - (pathRadius * sin(Math .toRadians(angle))).toFloat() + pathRadius
151+ val offsetY = (pathRadius * cos(Math .toRadians(angle))).toFloat() + pathRadius
152+ drawCircle(
153+ color = color,
154+ radius = when (i){
155+ 0 -> radius1
156+ 1 -> radius2
157+ 2 -> radius3
158+ 3 -> radius4
159+ 4 -> radius5
160+ 5 -> radius6
161+ 6 -> radius7
162+ 7 -> radius8
163+ 8 -> radius9
164+ 9 -> radius10
165+ 10 -> radius11
166+ 11 -> radius12
167+ else -> radius1
168+ },
169+ center = Offset (offsetX, offsetY)
170+ )
171+ }
172+ }
34173 }
35174}
0 commit comments