iOS炫酷动画(二)

作者: 微微笑的蜗牛 | 来源:发表于2016-06-03 23:24 被阅读319次

O(∩_∩)O哈!又是一个很cool的动画。原作者在这里。画面看着太美好,于是又试着用Swift写了一个。我的在这里

1.gif
动画分解

1、首先是椭圆背景色的渐变,灰色---》淡蓝色。

2、脸的动画。这里又分为脸盘(😄就这么叫吧)和器官(2眼睛+1嘴巴)的动画。

  • 脸盘的动画,比较简单,就是x的位移。
  • 眼睛+嘴巴这个整体的动画,有个回弹的效果。先是向右飞出去,然后到达右边之后,又从左边飞进来,最后回弹一下。

3、嘴巴的动画。off的时候,是个长方形的嘴,切换到on,变成了笑脸嘴,并且有个逐渐张开的过程。

AIYA,还真是难描述。

元素分解

知道了动画步骤之后,元素就比较好分了。脸盘是1个layer,2眼睛+嘴巴==1个layer,椭圆背景=1view。

开工开工
嘴巴

首先注意到的是嘴巴的绘制,on和off的状态其实是2种不同的曲线,长方形很好画,那么张开的嘴呢?当然都是用万能的贝塞尔曲线啦。其实看了代码,都觉得简单o(>﹏<)o。

闭嘴的frame=(0.25w, 0.7h, 0.5w, 0.1h)
张嘴的,x,y,w都是一样的,只不过是控制2个control point的位置。

private func mouthPath() -> UIBezierPath {
        
        if isOn {
            let path = UIBezierPath()

            path.moveToPoint(CGPointMake(mouthRect().origin.x, mouthRect().origin.y))
            path.addCurveToPoint(CGPointMake(mouthLenth() + mouthRect().origin.x, mouthY()), controlPoint1: CGPointMake(mouthRect().origin.x + mouthOffset / 4, mouthY() + mouthOffset / 2),
                                 controlPoint2: CGPointMake(mouthRect().origin.x + mouthOffset * 3 / 4, mouthY() + mouthOffset / 2))
            path.closePath()
            
            return path
        } else {
            let path = UIBezierPath(rect: mouthRect())
            return path
        }
    }

眼睛

眼睛就是2个椭圆,有现成的。frame=(0.2w, 0.25h, 0.4w, 0.6h)

private func rightEyePath() -> UIBezierPath {
        let origin = rightEyeOrigin()
        let size = eyeSize()
        let path = UIBezierPath(ovalInRect: CGRectMake(origin.x, origin.y, size.width, size.height))
        
        return path
    }
眼睛+嘴巴

其实就是在layer上面,分别把他们画上去。

override func drawInContext(ctx: CGContext) {
        
        let bezierLeft = leftEyePath()
        let bezierRight = rightEyePath()
        let bezierMouth = mouthPath()
        
        CGContextAddPath(ctx, bezierLeft.CGPath)
        CGContextAddPath(ctx, bezierRight.CGPath)
        CGContextAddPath(ctx, bezierMouth.CGPath)
        CGContextSetFillColorWithColor(ctx, color().CGColor)
        CGContextSetStrokeColorWithColor(ctx, UIColor.clearColor().CGColor)
        CGContextFillPath(ctx)
    }

脸盘/椭圆背景

这个更简单了,用cornerRadius或者bezierPath都行。

嘴张开的动画

因为嘴是用bezier曲线画的,有2个control point。所以主要是操控control point,来实现张开的效果。

为了支持自定义属性动画,需要用到needsDisplayForKey,改变属性后,可以引发drawInContext重绘。mouthOffset最后其实是等于mounLength的,所以只需要将mouthOffset从0变到mounLength即可。

internal override class func needsDisplayForKey(key: String) -> Bool {
        if key == "mouthOffset" {
            return true
        }
        
        return super.needsDisplayForKey(key)
    }
    
动画顺序

拿从off到on的过程来说。
1、背景渐变+脸盘移动+器官向右飞出
2、脸盘移动的动画结束后,器官从左往右飞出,并回弹。同时嘴巴开始张开动画。
3、回弹动画结束,整个动画结束。

动画注意

在动画结束之后,要将对应值设成动画之后的值。

override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        if flag {
            if let type = anim.valueForKey("animation") as? String {
                // 脸盘移动到端点
                if type == "faceBgLayerAnimation" {
                    
                    faceBgLayer.removeAllAnimations()
                    faceBgLayer.position = positionOfFaceView(!isOn)
                    
                    faceLayer.isOn = !isOn
                    faceLayer.mouthOffset = !isOn ? faceLayer.bounds.size.width / 2 : 0
                    faceLayer.setNeedsDisplay()
                
                    if (!isOn) {
                        mouthAnimation(isOn, offset: faceLayer.bounds.size.width / 2)
                        moveRightBackAnimation()
                    } else {
                        moveLeftBackAnimation()
                    }
                } else if type == "backgroundAnimation" {
                    
                    self.backgroundColor = isOn ? onColor : offColor
                    
                } else if type == "moveBackAnimation" {
                    
                    faceLayer.removeAllAnimations()

                    isOn = !isOn
                    isAnimating = false
                }
            }
        }
    }

相关文章

  • 炫酷转场动画-iOS

    炫酷转场动画-iOS 炫酷转场动画-iOS

  • iOS 常用第三方-动画

    常见动画 awesome-ios-animation - iOS Animation 主流炫酷动画框架(特效)收集...

  • iOS炫酷动画(二)

    O(∩_∩)O哈!又是一个很cool的动画。原作者在这里。画面看着太美好,于是又试着用Swift写了一个。我的在这...

  • 【功能实现】效果实现收集

    iOS动画进阶 - 手摸手教你写ShineButton动画 web图片放大预览 炫酷菜单弹射动画:SDiffuse...

  • 炫酷菜单弹射动画:SDiffuseMenu(AwesomeMen

    炫酷菜单弹射动画:SDiffuseMenu(AwesomeMenu) 炫酷菜单弹射动画:SDiffuseMenu(...

  • UIView Animation 学习笔记

    iOS 平台下酷炫而流畅的动画效果着实值得标榜,恰当的时机加入动画效果可以极大的提升用户体验。iOS 平台的动画,...

  • iOS动画三板斧(一)--UIView动画

    前言 iOS 精致的app,离不开酷炫合宜的动画。而iOS中的动画实现也有多种不同的方式。今天就来介绍一下iOS中...

  • iOS动画之UIView动画

    iOS酷炫的动画效果可以很好的增强用户体验。在iOS开发中实现动画的方式有多种,一般而言,简单的动画使用UIKit...

  • 炫酷转场动画-iOS

    2018-05-17增加CATransition动画 使用方法 1、导入头文件UIViewController+H...

  • iOS炫酷动画(一)

    最近,看到一个很炫酷的动画。效果是这样的。在进行切换的时候,会有一个线跑的动画。于是乎参照着用swift做了一份。...

网友评论

  • PGOne爱吃饺子:为毛楼主老是用swift开发啊 ,啊啊啊啊啊,难道oc真的不行了么,希望楼主以后来个oc版本的demo,么么哒
    PGOne爱吃饺子:@我落泪_情绪零碎 也写一个oc版本的吧,深的以后忘记oc咋写的了:grin: :grin:
    微微笑的蜗牛:@4140d18ee6fc swift练下手:smile:
  • 大墙66370:您好 楼主.我想问您一个 问题. 相信你oc篇的一定看过了吧..
    我在读oc篇的源码时遇见一个问题
    就是比如说 默认情况下开关是 关闭的
    当 打开开关 嘴巴张开 这个过程中 执行了一个关键帧动画 如下
    for (int i = 0; i < frameNumber; i++) {
    if (on) {
    frameValue = frameValue - offSet / frameNumber;
    } else {
    frameValue = frameValue + offSet / frameNumber;
    }
    [arrayFrame addObject:@(frameValue)];
    }
    我不太明白这个关键帧数组代表的是神马. 还有一个问题_mouthOffSet由于神马原因在 不断地改变.
    大墙66370:@summer_liu 谢谢,这么晚了还回复我,是不是程序员日常都是两点后睡觉啊:smile:明天我再看看代码。看看我能明白不
    微微笑的蜗牛:@大墙66370 offest的改变是为了改变controlpoint。
    微微笑的蜗牛:@大墙66370 因为自定义了动画的property,在相应属性变化时,会进行重绘。调用draw的那个方法。
  • xxttw:oc版本呢
    微微笑的蜗牛: @Unc1eWang 最上面给了

本文标题:iOS炫酷动画(二)

本文链接:https://www.haomeiwen.com/subject/urdldttx.html