Skip to content

Instantly share code, notes, and snippets.

@apkelly
Last active September 16, 2021 23:11
Show Gist options
  • Save apkelly/b8ef9a3b0c64d15d17b833899e4ed122 to your computer and use it in GitHub Desktop.
Save apkelly/b8ef9a3b0c64d15d17b833899e4ed122 to your computer and use it in GitHub Desktop.
Matrix Animation
import android.graphics.Typeface
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalDensity
import kotlinx.coroutines.delay
import kotlin.random.Random
private val characters = listOf("ジ", "ェ", "ッ", "ト", "パ", "Z", "A", "R", "Q", "ッ", "ク", "構", "成", "I", "L", "N", "K", "8", "7", "C", "6")
@Composable
fun MatrixText(
stripCount: Int = 20,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier.background(Color.Black)
) {
for (columns in 0..stripCount) {
MatrixColumn(
Random.nextInt(8) * 1000L,
(Random.nextInt(10) * 10L) + 100
)
}
}
}
@Composable
fun RowScope.MatrixColumn(
yStartDelay: Long,
crawlSpeed: Long
) {
BoxWithConstraints(
modifier = Modifier
.fillMaxHeight()
.weight(1f)
) {
val pxWidth = with(LocalDensity.current) { maxWidth.toPx() }
val pxHeight = with(LocalDensity.current) { maxHeight.toPx() }
val paint = Paint().asFrameworkPaint().apply {
isAntiAlias = true
textSize = pxWidth
typeface = Typeface.SANS_SERIF
}
val matrixStrip =
remember { Array((pxHeight / paint.textSize).toInt() + 1) { characters.random() } }
val lettersToDraw = remember { mutableStateOf(Random.nextInt(matrixStrip.size)) }
Canvas(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
) {
for (i in 0 until lettersToDraw.value) {
val yPoint = i * paint.textSize
if (i == lettersToDraw.value - 1) {
paint.color = 0xffcefbe4.toInt()
} else {
paint.color = Color(0xff43c728)
.copy(alpha = i / lettersToDraw.value.toFloat())
.toArgb()
}
drawIntoCanvas {
it.nativeCanvas.drawText(matrixStrip[i], 0f, yPoint, paint)
}
}
}
LaunchedEffect(key1 = yStartDelay) {
delay(yStartDelay)
while (true) {
lettersToDraw.value += 1
if (lettersToDraw.value > matrixStrip.size) {
lettersToDraw.value = 0
}
if (lettersToDraw.value > matrixStrip.size * 0.5) {
// If we've drawn over half the strip, we can randomly change letters.
matrixStrip[Random.nextInt(lettersToDraw.value)] = characters.random()
}
delay(crawlSpeed)
}
}
}
}
@apkelly
Copy link
Author

apkelly commented Sep 16, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment