Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 24 additions & 4 deletions
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

Lines changed: 37 additions & 87 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /