Compose自定义View实现宇智波斑写轮眼
cxy107750 人气:0正文
本章节是Compose自定义绘制的第二章,画的是一个之前设计给的一个比较复杂的,设计所谓的会呼吸的动画,那时候实现花了蛮长的时间,搬着电脑跟设计一帧一帧地对,没多久后来需求就被拿掉了,至于文章的标题哈哈随意起了一个,长得有点像而已。
Compose的实现,图形本身跟上一章节的LocationMarker其实差不太多,倒过来了而已,调整了P1跟P3, 基本图形的Path,这里不再做介绍,读者也可以去看代码实现。主要介绍一下动画吧。
首先看一下gif动图:
整个图形分三层,最底层是灰色的背景,没有动画实现。
先实现功能效果
第二层是一个层变的动画,每层有个delay的不同延迟,对alpha最一个ObjectAnimator.ofFloat(water1, "alpha", 0f, 0.5f, 0.2f, 1f)渐变的动画,0.5f 到0.2f, 再到1f这个地方展现出所谓的呼吸的感觉。Compose目前写的不多,有些冗余代码没有抽象,先实现了功能效果。
@Composable fun drawWaterDrop(){ val waterDropModel by remember { mutableStateOf(WaterDropModel.waterDropM) } val color1 = colorResource(id = waterDropModel.water1.colorResource) val color2 = colorResource(id = waterDropModel.water2.colorResource) val color3 = colorResource(id = waterDropModel.water3.colorResource) val color4 = colorResource(id = waterDropModel.water4.colorResource) val color5 = colorResource(id = waterDropModel.water5.colorResource) val color6 = colorResource(id = waterDropModel.water6.colorResource) val color7 = colorResource(id = waterDropModel.water7.colorResource) val color8 = colorResource(id = waterDropModel.water8.colorResource) val animAlpha1 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha2 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha3 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha4 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha5 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha6 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha7 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha8 = remember { Animatable(0f, Float.VectorConverter) } LaunchedEffect(Unit){ animAlpha1.animateTo(1f, animationSpec = myKeyframs(0)) } LaunchedEffect(Unit){ animAlpha2.animateTo(1f, animationSpec = myKeyframs(1)) } LaunchedEffect(Unit){ animAlpha3.animateTo(1f, animationSpec = myKeyframs(2)) } LaunchedEffect(Unit){ animAlpha4.animateTo(1f, animationSpec = myKeyframs(3)) } LaunchedEffect(Unit){ animAlpha5.animateTo(1f, animationSpec = myKeyframs(4)) } LaunchedEffect(Unit){ animAlpha6.animateTo(1f, animationSpec = myKeyframs(5)) } LaunchedEffect(Unit){ animAlpha7.animateTo(1f, animationSpec = myKeyframs(6)) } LaunchedEffect(Unit){ animAlpha8.animateTo(1f, animationSpec = myKeyframs(7)) } Canvas(modifier = Modifier.fillMaxSize()){ val contentWidth = size.width val contentHeight = size.height withTransform({ translate(left = contentWidth / 2, top = contentHeight / 2)}) { drawPath(AndroidPath(waterDropModel.water8Path), color = color8, alpha = animAlpha8.value) drawPath(AndroidPath(waterDropModel.water7Path), color = color7, alpha = animAlpha7.value) drawPath(AndroidPath(waterDropModel.water6Path), color = color6, alpha = animAlpha6.value) drawPath(AndroidPath(waterDropModel.water5Path), color = color5, alpha = animAlpha5.value) drawPath(AndroidPath(waterDropModel.water4Path), color = color4, alpha = animAlpha4.value) drawPath(AndroidPath(waterDropModel.water3Path), color = color3, alpha = animAlpha3.value) drawPath(AndroidPath(waterDropModel.water2Path), color = color2, alpha = animAlpha2.value) drawPath(AndroidPath(waterDropModel.water1Path), color = color1, alpha = animAlpha1.value) } } } private fun myKeyframs(num:Int):KeyframesSpec<Float>{ return keyframes{ durationMillis = 3000 delayMillis = num * 2000 0.5f at 1000 with LinearEasing 0.2f at 2000 with LinearEasing } }
调用传入不同的delay值
然后就是外层扫光的动画,像探照灯一样一圈圈的扫,一共扫7遍,代码跟层变动画差不多,也是对alpha值做渐变,目前代码是调用扫光动画7次,后续看看如何优化性能。每次调用传入不同的delay值即可。
@Composable fun drawWaterDropScan(delayTime:Long){ val waterDropModel by remember { mutableStateOf(WaterDropModel.waterDropMScan) } val color1 = colorResource(id = waterDropModel.water1.colorResource) val color2 = colorResource(id = waterDropModel.water2.colorResource) val color3 = colorResource(id = waterDropModel.water3.colorResource) val color4 = colorResource(id = waterDropModel.water4.colorResource) val color5 = colorResource(id = waterDropModel.water5.colorResource) val color6 = colorResource(id = waterDropModel.water6.colorResource) val color7 = colorResource(id = waterDropModel.water7.colorResource) val color8 = colorResource(id = waterDropModel.water8.colorResource) val animAlpha2 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha3 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha4 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha5 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha6 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha7 = remember { Animatable(0f, Float.VectorConverter) } val animAlpha8 = remember { Animatable(0f, Float.VectorConverter) } LaunchedEffect(Unit){ delay(delayTime) val map = mutableMapOf<Float, Int>().apply { put(1f, 350) } animAlpha2.animateTo(0f, animationSpec = myKeyframs2(700, 0, map)) } LaunchedEffect(Unit){ delay(delayTime) val map = mutableMapOf<Float, Int>().apply { put(0.8f, 315) } animAlpha3.animateTo(0f, animationSpec = myKeyframs2(630, 233, map)) } LaunchedEffect(Unit){ delay(delayTime) val map = mutableMapOf<Float, Int>().apply { put(0.55f, 315) } animAlpha4.animateTo(0f, animationSpec = myKeyframs2(630, 383, map)) } LaunchedEffect(Unit){ delay(delayTime) val map = mutableMapOf<Float, Int>().apply { put(0.5f, 325) } animAlpha5.animateTo(0f, animationSpec = myKeyframs2(650, 533, map)) } LaunchedEffect(Unit){ delay(delayTime) val map = mutableMapOf<Float, Int>().apply { put(0.45f, 325) } animAlpha6.animateTo(0f, animationSpec = myKeyframs2(650, 667, map)) } LaunchedEffect(Unit){ delay(delayTime) val map = mutableMapOf<Float, Int>().apply { put(0.35f, 283) } animAlpha7.animateTo(0f, animationSpec = myKeyframs2(567, 816, map)) } LaunchedEffect(Unit){ delay(delayTime) val map = mutableMapOf<Float, Int>().apply { put(0.3f, 216) } animAlpha8.animateTo(0f, animationSpec = myKeyframs2(433, 983, map)) } Canvas(modifier = Modifier.fillMaxSize()){ val contentWidth = size.width val contentHeight = size.height withTransform({ translate(left = contentWidth / 2, top = contentHeight / 2) }) { drawPath(AndroidPath(waterDropModel.water8Path), color = color8, alpha = animAlpha8.value) drawPath(AndroidPath(waterDropModel.water7Path), color = color7, alpha = animAlpha7.value) drawPath(AndroidPath(waterDropModel.water6Path), color = color6, alpha = animAlpha6.value) drawPath(AndroidPath(waterDropModel.water5Path), color = color5, alpha = animAlpha5.value) drawPath(AndroidPath(waterDropModel.water4Path), color = color4, alpha = animAlpha4.value) drawPath(AndroidPath(waterDropModel.water3Path), color = color3, alpha = animAlpha3.value) drawPath(AndroidPath(waterDropModel.water2Path), color = color2, alpha = animAlpha2.value) drawPath(AndroidPath(waterDropModel.water1Path), color = color1) } } } private fun myKeyframs2(durationMillisParams:Int, delayMillisParams:Int, frames:Map<Float, Int>):KeyframesSpec<Float>{ return keyframes{ durationMillis = durationMillisParams delayMillis = delayMillisParams for ((valueF, timestamp) in frames){ valueF at timestamp } } } @Preview @Composable fun WaterDrop(){ Box(modifier = Modifier.fillMaxSize()){ drawWaterDropBg() drawWaterDrop() for (num in 1 .. 7){ drawWaterDropScan(delayTime = num * 2000L) } } }
代码跟LocationMarker在一个Project里面,暂时没有添加导航。github.com/yinxiucheng… 下的CustomerComposeView.
加载全部内容