• 作者:老汪软件技巧
  • 发表时间:2024-08-26 10:03
  • 浏览量:

背景

在网上看到几个有意思的卡片动画效果,不过使用css实现的,我现在用compose复刻一下,这篇文章的效果都是卡片相关的,而且使用compose实现的方式和css有些差异,思路不完全一样。本篇文章不提供完整代码,主要提供思路和细节代码。

1.渐变边框卡片

效果实现主要就是一个Brush,然后颜色写成动画,如果将这两个渐变颜色的出现时机修改一下,还可以实现从特定方向出现的效果:

val color1 by animateColorAsState(
    if (hover) Color(0, 219, 222) else Color.Transparent,
    tween(600) //修改这个地方
)
val color2 by animateColorAsState(
    if (hover) Color(252, 0, 255) else Color.Transparent,
    tween(1200)
)
Box(
    modifier = Modifier
        .size(190.dp, 250.dp)
        .background(Color.Black, shape)
        .hoverable(interactionSource)
        .border(
            3.dp, Brush.linearGradient(
                listOf(
                    color1, // 重点
                    color2, // 重点
                ),
                start = Offset.Zero,
                end = Offset(300f, 300f)
            ), shape
        )
    ,
    contentAlignment = Alignment.Center
) 

2.发光呼吸边框

代码如下:

val shape = remember { RoundedCornerShape(8.dp) }
val interactionSource = remember { MutableInteractionSource() }
val infiniteTransition = rememberInfiniteTransition()
val alpha by infiniteTransition.animateFloat(
    1f, 0.3f, infiniteRepeatable(
        tween(2000, 0, easing = FastOutLinearInEasing),
        repeatMode = RepeatMode.Reverse
    )
)
val radius by infiniteTransition.animateFloat(
    350f, 100f, infiniteRepeatable(
        tween(2000, 0, easing = FastOutLinearInEasing),
        repeatMode = RepeatMode.Reverse
    )
)
Box(
    modifier = Modifier
        .size(190.dp, 250.dp)
        .background(Color.Black, shape)
        .hoverable(interactionSource)
        .border(
            3.dp, Brush.radialGradient(
                listOf(
                    Color.White.copy(alpha),
                    Color.DarkGray,
                ),
                center = Offset.Zero,
                radius = radius
            ), shape
        ),
    contentAlignment = Alignment.Center
) {
    Icon(
        Icons.Outlined.Face,
        contentDescription = null,
        tint = Color.Cyan,
        modifier = Modifier
            .fillMaxSize(0.5f)
    )
}

3.流光边框

一个径向渐变,再加一个无限动画,让center一直沿着边框顺时针转。(注意,compose中的border是在组件之内,占据内部的大小)

//https://juejin.cn/post/7300784595619233819
//这个url是我发现这个效果的网址
@Composable
fun FlowingCard() {
    val shape = remember { RoundedCornerShape(8.dp) }
    var size by remember { mutableStateOf(IntSize.Zero) }
    val interactionSource = remember { MutableInteractionSource() }
    val hover by interactionSource.collectIsHoveredAsState()
    val infiniteTransition = rememberInfiniteTransition()
    val center by infiniteTransition.animateValue(
        Offset.Zero,
        Offset(size.width.toFloat(), size.height.toFloat()),
        typeConverter = Offset.VectorConverter,
        infiniteRepeatable(
            keyframes {
                durationMillis = 2000   //动画执行时长
                Offset.Zero at 0
                Offset(size.width.toFloat(), 0f) at 400
                Offset(size.width.toFloat(), size.height.toFloat()) at 1000
                Offset(0f, size.height.toFloat()) at 1400
                Offset.Zero at 2000
            },
            repeatMode = RepeatMode.Restart
        )
    )
    Box(
        modifier = Modifier
            .size(190.dp, 250.dp)
            .onGloballyPositioned {
                size = it.size
            }
            .background(Color.Black, shape)
            .hoverable(interactionSource)
            .border(
                4.dp, Brush.radialGradient(
                    listOf(
                        Color(1, 209, 125),
                        Color.Transparent
                    ),
                    center = center,
                    radius = 100f
                ), shape
            ),
        contentAlignment = Alignment.Center
    ) {
        Icon(
            Icons.Outlined.Face,
            contentDescription = null,
            tint = Color.Cyan,
            modifier = Modifier
                .fillMaxSize(0.5f)
        )
    }
}

总结

本文写了三个有趣的边框动画,可以用在类似Card组件的边框上,如果你有喜欢或者觉得有趣的动画,可以发在评论区,我可以学习实现。