如何在画布下方绘制像jetpack compose中的0.7路径一样的分段?

问题描述 投票:0回答:1

我想要为笔画路径设置动画,但我找不到分段动画的方法。如何在 jetpack compose 中从起点开始以 0.7 的路径分段在画布下方绘制?

  Canvas(modifier = Modifier.size(150.dp)) {
    val path = Path()
    val width: Float = size.width
    val height: Float = size.height
    path.apply {
        moveTo(width / 2, height / 5)
        cubicTo(
            5 * width / 14, 0f,
            0f, height / 15,
            width / 28, 2 * height / 5
        )
        cubicTo(
            width / 14, 2 * height / 3,
            3 * width / 7, 5 * height / 6,
            width / 2, height
        )
        cubicTo(
            4 * width / 7, 5 * height / 6,
            13 * width / 14, 2 * height / 3,
            27 * width / 28, 2 * height / 5
        )
        cubicTo(
            width, height / 15,
            9 * width / 14, 0f,
            width / 2, height / 5
        )
    }
    drawPath(color = Color.Red, path = path, style = Stroke(8f))
}
android-jetpack-compose android-jetpack
1个回答
0
投票

您可以使用

val pathMeasure by remember { mutableStateOf(PathMeasure()) }
进行操作,并使用

设置开始和结束距离
pathWithProgress.reset()

pathMeasure.setPath(path, forceClosed = false)
pathMeasure.getSegment(
    startDistance = 0f,
    stopDistance = pathMeasure.length * progress,
    pathWithProgress,
    startWithMoveTo = true
)

下面的代码片段从路径的 0.7f 开始,根据进度,我使用了滑块进行演示,但它可以很容易地进行动画化,可以绘制到完整的路径长度。

结果

代码

@Preview
@Composable
private fun Test() {

    var progress1 by remember {
        mutableStateOf(0.7f)
    }

    val transition: InfiniteTransition = rememberInfiniteTransition(label = "heart animation")

    // Infinite phase animation for PathEffect
    val progress2 by transition.animateFloat(
        initialValue = 0f,
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            animation = tween(
                durationMillis = 1500,
                easing = FastOutSlowInEasing
            ),
        ), label = "heart animation"
    )


    // This is the progress path which wis changed using path measure
    val pathWithProgress by remember {
        mutableStateOf(Path())
    }

    // using path
    val pathMeasure by remember { mutableStateOf(PathMeasure()) }

    val path = remember {
        Path()
    }

    Column(
        Modifier
            .fillMaxSize()
            .padding(20.dp)
    ) {

        Text(text = "Progress1: $progress1")
        Slider(
            value = progress1,
            onValueChange = { progress1 = it },
            valueRange = 0.7f..1f
        )

        Canvas(modifier = Modifier.size(150.dp)) {
            val width: Float = size.width
            val height: Float = size.height

            if (path.isEmpty) {
                path.apply {
                    moveTo(width / 2, height / 5)
                    cubicTo(
                        5 * width / 14, 0f,
                        0f, height / 15,
                        width / 28, 2 * height / 5
                    )
                    cubicTo(
                        width / 14, 2 * height / 3,
                        3 * width / 7, 5 * height / 6,
                        width / 2, height
                    )
                    cubicTo(
                        4 * width / 7, 5 * height / 6,
                        13 * width / 14, 2 * height / 3,
                        27 * width / 28, 2 * height / 5
                    )
                    cubicTo(
                        width, height / 15,
                        9 * width / 14, 0f,
                        width / 2, height / 5
                    )
                }
            }

            pathWithProgress.reset()

            pathMeasure.setPath(path, forceClosed = false)
            pathMeasure.getSegment(
                startDistance = 0f,
                stopDistance = pathMeasure.length * progress1,
                pathWithProgress,
                startWithMoveTo = true
            )

            drawPath(color = Color.Red, path = pathWithProgress, style = Stroke(8f))

            pathWithProgress.reset()

            pathMeasure.setPath(path, forceClosed = false)
            pathMeasure.getSegment(
                startDistance = 0f,
                stopDistance = pathMeasure.length * progress2,
                pathWithProgress,
                startWithMoveTo = true
            )

            translate(left = 500f) {
                drawPath(color = Color.Blue, path = pathWithProgress, style = Stroke(8f))
            }

        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.