Compose眼珠跟随手势移动的笑脸


前言

阅读本文需要一定compose基础,如果没有请移步Jetpack Compose入门详解(实时更新)

在网上看到有人用css写出了下面这种效果;原文链接

请添加图片描述

我看到了觉得很好玩,于是用Compose撸了一个随手势移动眼珠的版本。


一、Canvas画图

这种笑脸常用的控件肯定实现不了,我们只能用Canvas自己画了

笑脸

我们先画脸

下例当中的size和center都是onDraw 的DrawScope提供的属性,drawCircle则是DrawScope提供的画圆的方法

Canvas(modifier = modifier
        .size(300.dp),
        onDraw = {

           // 脸
            drawCircle(
                color = Color(0xfffecd00),
                radius = size.width / 2,
                center = center
            )

    })

属性解释

  • color:填充颜色
  • radius: 半径
  • center: 圆心坐标

这里我们半径取屏幕宽度一半,圆心取屏幕中心,画出来的脸效果如下

在这里插入图片描述

微笑

微笑是一个弧形,我们使用drawArc来画微笑

// 微笑
        val smilePadding = size.width / 4

        drawArc(
            color = Color(0xffb57700),
            startAngle = 0f,
            sweepAngle = 180f,
            useCenter = true,
            topLeft = Offset(smilePadding, size.height / 2 - smilePadding / 2),
            size = Size(size.width / 2, size.height / 4)
        )

属性解释

  • color:填充颜色
  • startAngle: 弧形开始的角度,默认以3点钟方向为0度
  • sweepAngle:弧形结束的角度,默认以3点钟方向为0度
  • useCenter :指示圆弧是否要闭合边界中心的标志(上例加不加都无所谓)
  • topLeft :相对于当前平移从0的本地原点偏移,0开始
  • size:要绘制的圆弧的尺寸

效果如下
在这里插入图片描述

眼睛和眼珠子

眼睛也是drawCircle方法,只是位置不同,这边就不再多做解释

            // 左眼
            drawCircle(
                color = Color.White,
                center = Offset(smilePadding, size.height / 2 - smilePadding / 2),
                radius = smilePadding / 2
            )


                //左眼珠子
                drawCircle(
                    color = Color.Black,
                    center = Offset(smilePadding, size.height / 2 - smilePadding / 2),
                    radius = smilePadding / 4
                )



            // 右眼
            drawCircle(
                color = Color.White,
                center = Offset(smilePadding * 3, size.height / 2 - smilePadding / 2),
                radius = smilePadding / 2
            )


                //右眼珠子
                drawCircle(
                    color = Color.Black,
                    center = Offset(smilePadding * 3, size.height / 2 - smilePadding / 2),
                    radius = smilePadding / 4
                )

整个笑脸就画出来了,效果如下

在这里插入图片描述

二、跟随手势移动

在实现功能之前我们需要介绍transformableanimateFloatAsStatetranslate

transformable

transformablemodifier用于平移、缩放和旋转的多点触控手势的修饰符,此修饰符本身不会转换元素,只会检测手势。

animateFloatAsState

animateFloatAsState 是通过Float状态变化来控制动画 的状态

知道了这两个玩意过后我们就可以先通过transformable监听手势滑动然后通过translate方法和animateFloatAsState方法组成一个平移动画来实现眼珠跟随手势移动

完整的代码:

@Composable
fun SmileyFaceCanvas(
    modifier: Modifier
) {

    var x by remember {
        mutableStateOf(0f)
    }

    var y by remember {
        mutableStateOf(0f)
    }

    val state = rememberTransformableState { _, offsetChange, _ ->

        x = offsetChange.x
        if (offsetChange.x >50f){
            x = 50f
        }

        if (offsetChange.x < -50f){
            x=-50f
        }

        y = offsetChange.y
        if (offsetChange.y >50f){
            y= 50f
        }

        if (offsetChange.y < -50f){
            y=-50f
        }
    }

    val animTranslateX by animateFloatAsState(
        targetValue = x,
        animationSpec = TweenSpec(1000)
    )

    val animTranslateY by animateFloatAsState(
        targetValue = y,
        animationSpec = TweenSpec(1000)
    )



    Canvas(
        modifier = modifier
            .size(300.dp)
            .transformable(state = state)
    ) {



        // 脸
        drawCircle(
            Color(0xfffecd00),
            radius = size.width / 2,
            center = center
        )

        // 微笑
        val smilePadding = size.width / 4

        drawArc(
            color = Color(0xffb57700),
            startAngle = 0f,
            sweepAngle = 180f,
            useCenter = true,
            topLeft = Offset(smilePadding, size.height / 2 - smilePadding / 2),
            size = Size(size.width / 2, size.height / 4)
        )

        // 左眼
        drawCircle(
            color = Color.White,
            center = Offset(smilePadding, size.height / 2 - smilePadding / 2),
            radius = smilePadding / 2
        )

        translate(left = animTranslateX, top = animTranslateY) {
            //左眼珠子
            drawCircle(
                color = Color.Black,
                center = Offset(smilePadding, size.height / 2 - smilePadding / 2),
                radius = smilePadding / 4
            )
        }


        // 右眼
        drawCircle(
            color = Color.White,
            center = Offset(smilePadding * 3, size.height / 2 - smilePadding / 2),
            radius = smilePadding / 2
        )

        translate(left = animTranslateX, top = animTranslateY) {
            //右眼珠子
            drawCircle(
                color = Color.Black,
                center = Offset(smilePadding * 3, size.height / 2 - smilePadding / 2),
                radius = smilePadding / 4
            )
        }


    }
}

为了不让眼珠子从眼眶里蹦出来,我们将位移的范围限制在了50以内,运行效果如下

在这里插入图片描述


总结

通过Canvas中的一些方法配合简单的动画API实现了这个眼珠跟随手势移动的笑脸😁

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我怀里的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值