|
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