注册
web

你看这个圆脸😁,又大又可爱~ (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实

作者:我怀里的猫
来源:juejin.cn/post/7272550100139098170
现了这个眼珠跟随手势移动的笑脸😁

0 个评论

要回复文章请先登录注册