|
1 | 1 | package com.smarttoolfactory.tutorial1_1basics.chapter6_graphics
|
2 | 2 |
|
3 | 3 | import android.graphics.Bitmap
|
4 | | -import android.media.Image |
5 | 4 | import androidx.compose.animation.core.Animatable
|
| 5 | +import androidx.compose.animation.core.LinearEasing |
6 | 6 | import androidx.compose.animation.core.tween
|
7 | 7 | import androidx.compose.foundation.Canvas
|
8 | 8 | import androidx.compose.foundation.Image
|
@@ -135,7 +135,7 @@ fun GraphicsLayerToImageBitmapSample() {
|
135 | 135 | }
|
136 | 136 | }
|
137 | 137 |
|
138 | | -data class Particle( |
| 138 | +data class TestParticle( |
139 | 139 | val initialCenter: Offset,
|
140 | 140 | val initialSize: Size,
|
141 | 141 | val initialAlpha: Float,
|
@@ -170,20 +170,14 @@ data class Particle(
|
170 | 170 | )
|
171 | 171 | }
|
172 | 172 |
|
173 | | -class ParticleController( |
174 | | -) { |
175 | | - var imageBitmap: ImageBitmap? = null |
176 | | - val particles = mutableStateListOf<Particle>() |
177 | | -} |
178 | | - |
179 | 173 | @Preview
|
180 | 174 | @Composable
|
181 | 175 | fun GraphicsLayerToParticles() {
|
182 | 176 | val coroutineScope = rememberCoroutineScope()
|
183 | 177 | val graphicsLayer = rememberGraphicsLayer()
|
184 | 178 |
|
185 | 179 | val particleList = remember {
|
186 | | - mutableStateListOf<Particle>() |
| 180 | + mutableStateListOf<TestParticle>() |
187 | 181 | }
|
188 | 182 |
|
189 | 183 | var particleSize by remember {
|
@@ -266,95 +260,51 @@ fun GraphicsLayerToParticles() {
|
266 | 260 | targetValue = 1f,
|
267 | 261 | animationSpec = tween(
|
268 | 262 | durationMillis = duration.toInt(),
|
269 | | -// easing = LinearEasing |
| 263 | + easing = LinearEasing |
270 | 264 | ),
|
271 | 265 | block = {
|
272 | 266 |
|
273 | 267 | val progress = this.value
|
274 | 268 |
|
275 | | - particleList.forEachIndexed { index, particle -> |
| 269 | + particleList.forEachIndexed { _, particle -> |
276 | 270 |
|
277 | 271 | 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 |
299 | 274 |
|
300 | | - if (animate) { |
| 275 | + val newX = |
| 276 | + posX + 3f * Random.nextFloat() |
| 277 | + val newY = posY - 15f * Random.nextFloat() |
301 | 278 |
|
| 279 | + particle.center = |
| 280 | + Offset(newX, newY) |
302 | 281 |
|
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 |
312 | 283 |
|
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 |
316 | 292 |
|
| 293 | + if (animateSize) { |
| 294 | + val radius = particle.radius |
| 295 | + val newRadius = |
| 296 | + radius - progress * decayFactor * particle.initialRadius / 100f |
317 | 297 |
|
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 | + } |
353 | 303 |
|
354 | | - if (progress == 1f) { |
355 | | - particle.alpha = 0f |
356 | | - } |
| 304 | + if (progress == 1f) { |
| 305 | + particle.alpha = 0f |
357 | 306 | }
|
| 307 | + |
358 | 308 | }
|
359 | 309 | }
|
360 | 310 |
|
@@ -383,7 +333,7 @@ fun GraphicsLayerToParticles() {
|
383 | 333 | // TODO Remove this and invalidate Canvas more gracefully
|
384 | 334 | drawCircle(color = Color.Transparent, radius = animatable.value)
|
385 | 335 |
|
386 | | - particleList.forEach { particle: Particle -> |
| 336 | + particleList.forEach { particle: TestParticle -> |
387 | 337 |
|
388 | 338 | if (particle.active) {
|
389 | 339 | // For debugging borders of particles
|
@@ -442,8 +392,8 @@ fun GraphicsLayerToParticles() {
|
442 | 392 | }
|
443 | 393 | }
|
444 | 394 |
|
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>() |
447 | 397 |
|
448 | 398 | val width = imageBitmap.width
|
449 | 399 | val height = imageBitmap.height
|
@@ -486,7 +436,7 @@ fun createParticles(imageBitmap: ImageBitmap, particleSize: Int): List<Particle>
|
486 | 436 | val size = particleSize * 1f
|
487 | 437 |
|
488 | 438 | particleList.add(
|
489 | | - Particle( |
| 439 | + TestParticle( |
490 | 440 | initialCenter = Offset(
|
491 | 441 | x = pixelCenterX.toFloat(),
|
492 | 442 | y = pixelCenterY.toFloat()
|
|
0 commit comments