Vivek Modi
Vivek Modi

Reputation: 7181

Draw Pulse animation in canvas in jetpack compose

I am learning pulse animation in jetpack compose. I made a pulse animation with the help of Box. I want to convert this animation view in Canvas. I only find a way to drawCircle in canvas. I didn't find helpful article. Can anyone help me on this? Thank

@Composable
fun PulsatingCircles() {
    Column {
        val infiniteTransition = rememberInfiniteTransition()
        val mediumCircleSize by infiniteTransition.animateValue(
            initialValue = 26.dp,
            targetValue = 25.dp,
            Dp.VectorConverter,
            animationSpec = infiniteRepeatable(
                animation = tween(500, easing = FastOutLinearInEasing),
                repeatMode = RepeatMode.Reverse
            )
        )
        val smallCircle by infiniteTransition.animateValue(
            initialValue = 18.dp,
            targetValue = 20.dp,
            Dp.VectorConverter,
            animationSpec = infiniteRepeatable(
                animation = tween(1000, easing = FastOutLinearInEasing),
                repeatMode = RepeatMode.Reverse
            )
        )
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(27.dp),
            contentAlignment = Alignment.Center
        ) {
            PulseCircle(
                size = mediumCircleSize,
                color = MaterialTheme.colors.primary.copy(alpha = 0.25f)
            )
            PulseCircle(
                size = smallCircle,
                color = MaterialTheme.colors.primary.copy(alpha = 0.25f)
            )
            PulseCircle(
                size = 10.dp,
                color = MaterialTheme.colors.primary
            )
        }
    }
}

@Composable
fun PulseCircle(
    size: Dp,
    color: Color = Color.White,
    borderWidth: Dp = 0.dp,
    borderColor: Color = Color.LightGray.copy(alpha = 0.0f)
) {
    Column(
        modifier = Modifier.wrapContentSize(Alignment.Center)
    ) {
        Box(
            modifier = Modifier
                .size(size)
                .clip(CircleShape)
                .background(color)
                .border(borderWidth, borderColor)
        )
    }
}

@Preview(showBackground = true)
@Composable
fun PreviewPulsatingCircles() {
    PulsatingCircles()
}

Wants to convert this into canvas

@Composable
fun NodeView(
    showTopLine: Boolean,
    showBottomLine: Boolean,
) {
    val circleSize = LocalDensity.current.run { 8.dp.toPx() }
    val strokeWidth = LocalDensity.current.run { 2.dp.toPx() }
    val brush = Brush.linearGradient(listOf(Color.Red, Color.Blue))

    Canvas(modifier = Modifier.fillMaxHeight()) {
        drawIntoCanvas {
            if (showTopLine) {
                drawLine(
                    brush = brush,
                    start = Offset(x = size.width / 2, y = 0F),
                    end = Offset(x = size.width / 2, y = size.height / 2),
                    strokeWidth = strokeWidth,
                )
            }
            if (showBottomLine) {
                drawLine(
                    brush = brush,
                    start = Offset(x = size.width / 2, y = size.height / 2),
                    end = Offset(x = size.width / 2, y = size.height),
                    strokeWidth = strokeWidth,
                )
            }
            drawCircle(
                Concrete,
                circleSize,
                Offset(size.width, size.height / 2)
            )
        }
    }
}

Upvotes: 0

Views: 892

Answers (1)

bylazy
bylazy

Reputation: 1305

Example for circles with scale animation:

@Composable
fun CirclesTest(){
    val transition = rememberInfiniteTransition()
    val scale1 by transition.animateFloat(initialValue = 1f,
        targetValue = .9f,
        animationSpec = infiniteRepeatable(tween(500),
            repeatMode = RepeatMode.Reverse)
    )
    val scale2 by transition.animateFloat(initialValue = .95f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(tween(250),
            repeatMode = RepeatMode.Reverse)
    )
    val circle1 = with(LocalDensity.current){60.dp.toPx()}
    val circle2 = with(LocalDensity.current){40.dp.toPx()}
    Canvas(modifier = Modifier.size(80.dp)) {
        scale(scale = scale1) {
            drawCircle(color = Color.Green, radius = circle1)
        }
        scale(scale = scale2) {
            drawCircle(color = Color.Blue, radius = circle2)
        }
    }
}

Upvotes: 0

Related Questions