我如何在 Jetpack Compose 的 Canvas 内更改动画或状态?

How i can animation or state change inside the Canvas in jetpack compose?

假设我有简单的可组合乐趣,其中有 Canvas

Canvas(modifier = Modifier
        .padding(start = 60.dp, end = 60.dp)
        .fillMaxSize(),
        onDraw = {
            val w = size.width
            val h = size.height

            val s1LineOffset = w / 4 - 10
            val s2LineOffset = w * 3 / 8 - 10

            drawImage(
                image = ImageBitmap.imageResource(
                    res = resources,
                    id = R.drawable.bttn
                ),
                topLeft = Offset(
                    x = b1StartOffset,
                    y = 0f
                )
            )
          }
        )

我想使用初始值和目标值的 canvas 大小来定义动画状态,但我不能这样做,因为我不能在绘图范围内使用它,这就是为什么我必须在Canvas 块,因此无法访问 Canvas 大小我该怎么办

val anim by ballAnim.animateFloat(
    initialValue = ,
    targetValue =,
    animationSpec =
)

这更像是一项简单的工作。只需创建并记住一个 MutableState<T> 值,然后在 Canvas 内更新它。例如,

var canvasSize by remember { mutableStateOf(IntSize()) }

Canvas(modifier = Modifier
        .padding(start = 60.dp, end = 60.dp)
        .fillMaxSize(),
        onDraw = {
    
            canvasSize = size //Assign it here
            val w = size.width
            val h = size.height

            val s1LineOffset = w / 4 - 10
            val s2LineOffset = w * 3 / 8 - 10

            drawImage(
                image = ImageBitmap.imageResource(
                    res = resources,
                    id = R.drawable.bttn
                ),
                topLeft = Offset(
                    x = b1StartOffset,
                    y = 0f
                )
            )
          }
        )
val anim by ballAnim.animateFloat(
        initialValue = canvasSize.width,
        targetValue = canvasSize.height, //whatever
        animationSpec = spring()
    )

其中一个选项是对一些规范化的值进行动画处理,并使用 onDraw 内的大小对其进行非规范化,例如:

val animNormalized by ballAnim.animateFloat(
    initialValue = 0.5,
    targetValue = 0.8,
    animationSpec =
)

Canvas(modifier = Modifier
        .padding(start = 60.dp, end = 60.dp)
        .fillMaxSize(),
        onDraw = {
            val w = size.width
            val h = size.height
           
            val anim = animNormalized * w
            ...
          }
        )