Skip to content

Commit 0c49de7

Browse files
update README.md and graphicsLayer samples
1 parent fe99006 commit 0c49de7

File tree

3 files changed

+64
-91
lines changed

3 files changed

+64
-91
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,6 @@ And run task to check for compiler reports for stability inside **build/compiler
414414
<br>
415415
[Composable metrics-Chris Banes](https://chrisbanes.me/posts/composable-metrics/)
416416
<br>
417+
[Creating a particle explosion animation in Jetpack Compose-Omkar Tenkale](https://proandroiddev.com/creating-a-particle-explosion-animation-in-jetpack-compose-4ee42022bbfa)
418+
<br>
419+

Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter6_graphics/ParticlePhysics.kt

+24-4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fun ControlledExplosion() {
4343
mutableFloatStateOf(1f)
4444
}
4545

46+
4647
val particleCount = 1
4748

4849
val density = LocalDensity.current
@@ -60,14 +61,26 @@ fun ControlledExplosion() {
6061
visibilityThresholdHigh
6162
) {
6263
List(particleCount) {
64+
65+
val initialDisplacementX: Float = 1f
66+
val initialDisplacementY: Float = 1f
67+
68+
69+
// with(density) {
70+
// initialDisplacementX = 10.dp.toPx() * randomInRange(-1f, 1f)
71+
// initialDisplacementY = 10.dp.toPx() * randomInRange(-1f, 1f)
72+
// }
73+
6374
ExplodingParticle(
6475
color = Color(listOf(0xffea4335, 0xff4285f4, 0xfffbbc05, 0xff34a853).random()),
6576
startXPosition = sizePxHalf.toInt(),
6677
startYPosition = sizePxHalf.toInt(),
6778
maxHorizontalDisplacement = sizePxHalf,
6879
maxVerticalDisplacement = sizePxHalf,
6980
visibilityThresholdLow = visibilityThresholdLow,
70-
visibilityThresholdHigh = visibilityThresholdHigh
81+
visibilityThresholdHigh = visibilityThresholdHigh,
82+
initialDisplacementX = initialDisplacementX,
83+
initialDisplacementY = initialDisplacementY
7184
)
7285
}
7386
}
@@ -174,7 +187,9 @@ class ExplodingParticle(
174187
val maxHorizontalDisplacement: Float,
175188
val maxVerticalDisplacement: Float,
176189
val visibilityThresholdLow: Float,
177-
val visibilityThresholdHigh: Float
190+
val visibilityThresholdHigh: Float,
191+
val initialDisplacementX: Float,
192+
val initialDisplacementY: Float
178193
) {
179194
private val velocity = 4 * maxVerticalDisplacement
180195
private val acceleration = -2 * velocity
@@ -211,11 +226,16 @@ class ExplodingParticle(
211226
currentTime = trajectoryProgress
212227
// .mapInRange(0f, 1f, 0f, 1.4f)
213228

229+
// While trajectory progress is less than 70% have full alpha then slowly cre
230+
alpha = if (trajectoryProgress < .7f) 1f else
231+
scale(.7f, 1f, trajectoryProgress, 1f, 0f)
232+
214233
val verticalDisplacement =
215234
currentTime * velocity + 0.5 * acceleration * currentTime * currentTime
216235

217-
currentXPosition = startXPosition + maxHorizontalDisplacement * trajectoryProgress
218-
currentYPosition = (startYPosition - verticalDisplacement).toFloat()
236+
currentXPosition =
237+
startXPosition + initialDisplacementX + maxHorizontalDisplacement * trajectoryProgress
238+
currentYPosition = (startYPosition + initialDisplacementY - verticalDisplacement).toFloat()
219239

220240
}
221241
}

Tutorial1-1Basics/src/main/java/com/smarttoolfactory/tutorial1_1basics/chapter6_graphics/Tutorial6_39_1GraphicsLayer1.kt

+37-87
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.smarttoolfactory.tutorial1_1basics.chapter6_graphics
22

33
import android.graphics.Bitmap
4-
import android.media.Image
54
import androidx.compose.animation.core.Animatable
5+
import androidx.compose.animation.core.LinearEasing
66
import androidx.compose.animation.core.tween
77
import androidx.compose.foundation.Canvas
88
import androidx.compose.foundation.Image
@@ -135,7 +135,7 @@ fun GraphicsLayerToImageBitmapSample() {
135135
}
136136
}
137137

138-
data class Particle(
138+
data class TestParticle(
139139
val initialCenter: Offset,
140140
val initialSize: Size,
141141
val initialAlpha: Float,
@@ -170,20 +170,14 @@ data class Particle(
170170
)
171171
}
172172

173-
class ParticleController(
174-
) {
175-
var imageBitmap: ImageBitmap? = null
176-
val particles = mutableStateListOf<Particle>()
177-
}
178-
179173
@Preview
180174
@Composable
181175
fun GraphicsLayerToParticles() {
182176
val coroutineScope = rememberCoroutineScope()
183177
val graphicsLayer = rememberGraphicsLayer()
184178

185179
val particleList = remember {
186-
mutableStateListOf<Particle>()
180+
mutableStateListOf<TestParticle>()
187181
}
188182

189183
var particleSize by remember {
@@ -266,95 +260,51 @@ fun GraphicsLayerToParticles() {
266260
targetValue = 1f,
267261
animationSpec = tween(
268262
durationMillis = duration.toInt(),
269-
// easing = LinearEasing
263+
easing = LinearEasing
270264
),
271265
block = {
272266

273267
val progress = this.value
274268

275-
particleList.forEachIndexed { index, particle ->
269+
particleList.forEachIndexed { _, particle ->
276270

277271
if (particle.active) {
278-
val posX = particle.initialCenter.x
279-
val posY = particle.initialCenter.y
280-
281-
282-
val range = progress
283-
284-
val columnFraction =
285-
index / (particleList.size.toFloat())
286-
287-
val columnSection = columnFraction * 100
288-
289-
val animate = columnFraction < range
290-
291-
val sectionBasedProgress =
292-
scale(
293-
a1 = columnFraction,
294-
b1 = 1f,
295-
x1 = progress,
296-
a2 = 0f,
297-
b2 = 1f
298-
)
272+
val posX = particle.center.x
273+
val posY = particle.center.y
299274

300-
if (animate) {
275+
val newX =
276+
posX + 3f * Random.nextFloat()
277+
val newY = posY - 15f * Random.nextFloat()
301278

279+
particle.center =
280+
Offset(newX, newY)
302281

303-
println(
304-
"progress: $progress, " +
305-
"sectionBasedProgress: $sectionBasedProgress, " +
306-
"columnFraction: $columnFraction, " +
307-
"columnSection: $columnSection, " +
308-
"range: $range," +
309-
" index: $index, " +
310-
"animate: $animate"
311-
)
282+
val particleDecayFactor = particle.decayFactor
312283

313-
val velocityX = -30f + (60f) * Random.nextFloat()
314-
val velocityY =
315-
-40f * Random.nextInt(100, 150) / 100f
284+
val decayFactor =
285+
if (progress < .80f) particleDecayFactor
286+
else if (progress < .85f) particleDecayFactor + 1
287+
else if (progress < .9f) particleDecayFactor + 4
288+
else if (progress < .97)
289+
particleDecayFactor
290+
.coerceAtLeast(5) + 1
291+
else 1
316292

293+
if (animateSize) {
294+
val radius = particle.radius
295+
val newRadius =
296+
radius - progress * decayFactor * particle.initialRadius / 100f
317297

318-
val newX =
319-
posX + velocityX * sectionBasedProgress
320-
val newY = posY + velocityY * sectionBasedProgress
321-
322-
particle.center =
323-
Offset(newX, newY)
324-
325-
val particleDecayFactor = particle.decayFactor
326-
327-
val decayFactor =
328-
if (progress < .80f) particleDecayFactor
329-
else if (progress < .85f) particleDecayFactor + 1
330-
else if (progress < .9f) particleDecayFactor + 4
331-
else
332-
particleDecayFactor
333-
.coerceAtLeast(5) + 1
334-
335-
if (animateSize) {
336-
val radius = particle.radius
337-
val newRadius =
338-
radius - progress * decayFactor * particle.initialRadius / 100f
339-
340-
particle.radius = newRadius.coerceAtLeast(0f)
341-
342-
// println(
343-
// "Time passed: $timePassed, " +
344-
// "timeFraction: $timeFraction, " +
345-
// "newRadius: $newRadius, " +
346-
// "center: ${particle.center}"
347-
// )
348-
}
349-
//
350-
if (animateAlpha) {
351-
particle.alpha -= (progress) * Random.nextFloat() / 20f
352-
}
298+
particle.radius = newRadius.coerceAtLeast(0f)
299+
}
300+
if (animateAlpha) {
301+
particle.alpha -= (progress) * Random.nextFloat() / 20f
302+
}
353303

354-
if (progress == 1f) {
355-
particle.alpha = 0f
356-
}
304+
if (progress == 1f) {
305+
particle.alpha = 0f
357306
}
307+
358308
}
359309
}
360310

@@ -383,7 +333,7 @@ fun GraphicsLayerToParticles() {
383333
// TODO Remove this and invalidate Canvas more gracefully
384334
drawCircle(color = Color.Transparent, radius = animatable.value)
385335

386-
particleList.forEach { particle: Particle ->
336+
particleList.forEach { particle: TestParticle ->
387337

388338
if (particle.active) {
389339
// For debugging borders of particles
@@ -442,8 +392,8 @@ fun GraphicsLayerToParticles() {
442392
}
443393
}
444394

445-
fun createParticles(imageBitmap: ImageBitmap, particleSize: Int): List<Particle> {
446-
val particleList = mutableStateListOf<Particle>()
395+
fun createParticles(imageBitmap: ImageBitmap, particleSize: Int): List<TestParticle> {
396+
val particleList = mutableStateListOf<TestParticle>()
447397

448398
val width = imageBitmap.width
449399
val height = imageBitmap.height
@@ -486,7 +436,7 @@ fun createParticles(imageBitmap: ImageBitmap, particleSize: Int): List<Particle>
486436
val size = particleSize * 1f
487437

488438
particleList.add(
489-
Particle(
439+
TestParticle(
490440
initialCenter = Offset(
491441
x = pixelCenterX.toFloat(),
492442
y = pixelCenterY.toFloat()

0 commit comments

Comments
 (0)