欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS开发进阶 - 实现类似美颜相机的相机启动动画

程序员文章站 2022-03-23 14:13:03
最近在写一个相册的demo,偶尔看到了美拍的相机过载动画觉得很有意思,就想在我的相册demo中加入一个这种特效,下面把我的想法和实现过程给大家分享一下 先上效果图:(demo地址) 步骤分析...

最近在写一个相册的demo,偶尔看到了美拍的相机过载动画觉得很有意思,就想在我的相册demo中加入一个这种特效,下面把我的想法和实现过程给大家分享一下

先上效果图:(demo地址

iOS开发进阶 - 实现类似美颜相机的相机启动动画

步骤分析

这个动效看起来很有特色但是实现起来是非常简单的,只需要用到calayer和cashapelayer做为展示层,然后通过cabasicanimation实现动画就行了~

用两个calayer来呈现启动的image 通过uibezierpath和cashapelayer来画出具有曲线的cashapelayer 然后将曲线的cashapelayer做为calayer的mask 最后通过cabasicanimation做一个简单的位移动画

先绘制上半部分的layer

/**
     绘制上半部分的layer
     */
    private func configtopshapelayer() {
        //绘制贝斯尔曲线
        let topbezier:uibezierpath = uibezierpath()
        topbezier.movetopoint(cgpointmake(-1, -1))
        topbezier.addlinetopoint(cgpointmake(bounds.width+1, -1))
        topbezier.addcurvetopoint(cgpointmake(bounds.width/2.0+1, bounds.height/2.0+1), controlpoint1: cgpointmake(bounds.width+1, 0+1), controlpoint2: cgpointmake(343.5+1, 242.5+1))
        topbezier.addcurvetopoint(cgpointmake(-1, bounds.height+2), controlpoint1: cgpointmake(31.5+2, 424.5+2), controlpoint2: cgpointmake(0+2, bounds.height+2))
        topbezier.addlinetopoint(cgpointmake(-1, -1))
        topbezier.closepath()
        //创建一个cashapelayer,将绘制的贝斯尔曲线的path给cashapelayer
        let topshape = cashapelayer()
        topshape.path = topbezier.cgpath
        //给toplayer设置contents为启动图
        toplayer.contents = launchimage?.cgimage
        toplayer.frame = bounds
        layer.addsublayer(toplayer)
        //将绘制后的cashapelayer做为toplayer的mask
        toplayer.mask = topshape
    }

绘制后的结果是这样的:

iOS开发进阶 - 实现类似美颜相机的相机启动动画

然后以同样的原理绘制下半部分的layer

/**
     绘制下半部分的layer
     */
    private func configbottomshapelayer() {
        //绘制贝斯尔曲线
        let bottombezier:uibezierpath = uibezierpath()
        bottombezier.movetopoint(cgpointmake(bounds.width, 0))
        bottombezier.addcurvetopoint(cgpointmake(bounds.width/2.0, bounds.height/2.0), controlpoint1: cgpointmake(bounds.width, 0), controlpoint2: cgpointmake(343.5, 242.5))
        bottombezier.addcurvetopoint(cgpointmake(0, bounds.height), controlpoint1: cgpointmake(31.5, 424.5), controlpoint2: cgpointmake(0, bounds.height))
        bottombezier.addlinetopoint(cgpointmake(bounds.width, bounds.height))
        bottombezier.addlinetopoint(cgpointmake(bounds.width, 0))
        bottombezier.closepath()
        //创建一个cashapelayer,将绘制的贝斯尔曲线的path给cashapelayer
        let bottomshape = cashapelayer()
        bottomshape.path = bottombezier.cgpath
        //给bottomlayer设置contents为启动图
        bottomlayer.contents = launchimage?.cgimage
        bottomlayer.frame = bounds
        layer.addsublayer(bottomlayer)
        //将绘制后的cashapelayer做为bottomlayer的mask
        bottomlayer.mask = bottomshape
    }

这里注意的是画的贝斯尔曲线上半部分的要整体向下平移1到2个像素,为了防止贝斯尔曲线画曲线导致的锯齿效果,下面是下半部分完成后的效果图:

iOS开发进阶 - 实现类似美颜相机的相机启动动画

最后给两个layer一个位移动画

/**
     展开的动画
     */
    func staranimation() {
        //创建一个cabasicanimation作用于calayer的anchorpoint
        let topanimation = cabasicanimation.init(keypath: "anchorpoint")
        //设置移动路径
        topanimation.tovalue = nsvalue.init(cgpoint: cgpointmake(1, 1))
        //动画时间
        topanimation.duration = 0.6
        //设置代理,方便完成动画后移除当前view
        topanimation.delegate = self
        //设置动画速度为匀速
        topanimation.timingfunction = camediatimingfunction.init(name: kcamediatimingfunctionlinear)
        //设置动画结束后不移除点,保持移动后的位置
        topanimation.removedoncompletion = false
        topanimation.fillmode = kcafillmodeforwards
        toplayer.addanimation(topanimation, forkey: "topanimation")

        //创建一个cabasicanimation作用于calayer的anchorpoint
        let bottomanimation = cabasicanimation.init(keypath: "anchorpoint")
        //设置移动路径
        bottomanimation.tovalue = nsvalue.init(cgpoint: cgpointmake(0, 0))
        //动画时间
        bottomanimation.duration = 0.6
        //设置动画速度为匀速
        bottomanimation.timingfunction = camediatimingfunction.init(name: kcamediatimingfunctionlinear)
        //设置动画结束后不移除点,保持移动后的位置
        bottomanimation.removedoncompletion = false
        bottomanimation.fillmode = kcafillmodeforwards
        bottomlayer.addanimation(bottomanimation, forkey: "topanimation")
    }

        /**
     动画完成后移除当前view
     */
    internal override func animationdidstop(anim: caanimation, finished flag: bool)           
    {
        if flag {
            removefromsuperview()
        }
    }

这里为了方便观察,我将动画时间变长了,下面是完成后的效果图:

iOS开发进阶 - 实现类似美颜相机的相机启动动画

到这里这个动效就完成的差不多了,希望大家能学到东西,如果大家有更好的实现办法也可以给我提意见,我学习学习,谢谢大家观看,另外附加demo地址,喜欢的可以关注一下