代码之家  ›  专栏  ›  技术社区  ›  Abdullah

我如何在画布下面画出像喷气背包中0.7的路径一样分段的构图?

  •  0
  • Abdullah  · 技术社区  · 2 年前

    我想设置笔划路径的动画,但找不到分段动画的方法。我如何在画布下面画出从喷气背包组成的起点开始的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))
    }
    
    1 回复  |  直到 2 年前
        1
  •  2
  •   Thracian    2 年前

    你可以用 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开始,根据进度,我使用了Slider进行演示,但它可以很容易地被篡改,可以绘制到完整的路径长度。

    后果

    enter image description here

    密码

    @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))
                }
    
            }
        }
    }