本章节是Compose自定义绘制的第二章,画的是一个之前规划给的一个比较复杂的,规划所谓的会呼吸的动画,那时候完成花了蛮长的时间,搬着电脑跟规划一帧一帧地对,没多久后来需求就被拿掉了,至于文章的标题哈哈随意起了一个,长得有点像罢了。

Compose的完成,图形本身跟上一章节的LocationMarker其实差不太多,倒过来了罢了,调整了P1跟P3, 基本图形的Path,这儿不再做介绍,读者也能够去看代码完成。首要介绍一下动画吧。

首先看一下gif动图:

Compose自定义View——宇智波斑写轮眼

整个图形分三层,最底层是灰色的布景,没有动画完成。

第二层是一个层变的动画,每层有个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){
    async { animAlpha1.animateTo(1f, animationSpec = myKeyframs(0)) }
    async { animAlpha2.animateTo(1f, animationSpec = myKeyframs(1)) }
    async { animAlpha3.animateTo(1f, animationSpec = myKeyframs(2)) }
    async { animAlpha4.animateTo(1f, animationSpec = myKeyframs(3)) }
    async { animAlpha5.animateTo(1f, animationSpec = myKeyframs(4)) }
    async { animAlpha6.animateTo(1f, animationSpec = myKeyframs(5)) }
    async { animAlpha7.animateTo(1f, animationSpec = myKeyframs(6)) }
    async { 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
    }
}

然后便是外层扫光的动画,像探照灯相同一圈圈的扫,一共扫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){
    async {
        animAlpha2.animateTo(0f, animationSpec = myKeyframs2(700,  0 + delayCurrent,
            mutableMapOf<Float, Int>().apply { put(1f, 350) }))
    }
    async{
        animAlpha3.animateTo(0f, animationSpec = myKeyframs2(630, 233 + delayCurrent,
            mutableMapOf<Float, Int>().apply { put(0.8f, 315) }))
    }
    async{
        animAlpha4.animateTo(0f, animationSpec = myKeyframs2(630, 383 + delayCurrent,
            mutableMapOf<Float, Int>().apply { put(0.55f, 315) }))
    }
    async {
        animAlpha5.animateTo(0f, animationSpec = myKeyframs2(650, 533 + delayCurrent,
            mutableMapOf<Float, Int>().apply { put(0.5f, 325) }))
    }
    async {
        animAlpha6.animateTo(0f, animationSpec = myKeyframs2(650, 667 + delayCurrent,
            mutableMapOf<Float, Int>().apply { put(0.45f, 325) }))
    }
    async {
        animAlpha7.animateTo(0f, animationSpec = myKeyframs2(567, 816 + delayCurrent,
            mutableMapOf<Float, Int>().apply { put(0.35f, 283) }))
    }
    async {
        animAlpha8.animateTo(0f, animationSpec = myKeyframs2(433, 983 + delayCurrent,
            mutableMapOf<Float, Int>().apply { put(0.3f, 216) }))
    }
}
​
 Canvas(modifier = Modifier.fillMaxSize()){
 val contentWidth = size.width
 val contentHeight = size.heightwithTransform({
 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.