Layer Animation(三)

Tuesday, March 20, 2018

Shapes and Masks

  • layer 动画中,形状和遮罩也是可以实现动画效果的。

[WPGP gif_id="126” width="400”]

  • 上图中,两个头像相撞后,产生了压缩的动画效果

layer 部分动画属性

  • path: 将layer 的形状变为不同的形状
  • fillColor: 将形状的填充色调更改为不同的颜色
  • lineDashPhase: 在形状周围创建一个选取框
  • lineWidth: 增大或减小画笔的大小

头像的实现

  • 在讲解头像碰撞动画前,我们先看看这个头像是怎么生成的。

  • 我们将其拆分成几个 layer

    • photoLayer: 头像本身的内容
    • maskLayer: 遮罩层
    • circleLayer: 圆形图层
  • 通过上述3个 layer 的组合,即可实现该头像的效果。

    let photoLayer = CALayer() photoLayer.contents = image.cgImage layer.addSubLayer(photoLayer)

    let circleLayer = CAShapeLayer() circleLayer.path = UIBezierPath(ovalIn: bounds).cgPath circleLayer.lineWidth = lineWidth circleLayer.fillColor = UIColor.clear.cgColor

    let maskLayer = CAShapeLayer() maskLayer.path = circleLayer.path maskLayer.position = CGPoint(x: 0.0, y: 10.0)

    photoLayer.mask = maskLayer layer.addSubLayer(circleLayer)

碰撞动画

  • 首先我们进行动画拆分,先进行碰撞,再进行压缩。

  • 碰撞,也就是位移动画,压缩动画,也就是改变 layer 的大小

    //计算好位移的数据和 size 的数据 let avatarSize = myAvatar.frame.size let bounceXOffset: CGFloat = avatarSize.width / 1.9 let morphSize = CGSize(width: avatarSize.width * 0.85, height: avatarSize.height * 1.1)

    let rightBouncePoint = CGPoint(x: view.frame.size.width / 2.0 + bounceXOffset, y: myAvatar.center.y) let leftBouncePoint = CGPoint(x: view.frame.size.width / 2.0 - bounceXOffset, y: myAvatar.center.y)

    myAvatar.bounceOff(point: rightBouncePoint, morphSize: morphSize) opponentAvatar.bounceOff(point: leftBouncePoint, morphSize: morphSize)

    //进行循环的碰撞运动 func bounceOff(point: CGPoint, morphSize: CGSize) { let originalCenter = center UIView.animate(withDuration: animationDuration, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.0, animations: { self.center = point }, completion: {_ in //complete bounce to } ) }

    UIView.animate(withDuration: animationDuration, delay: animationDuration, usingSpringWithDamping: 0.7, initialSpringVelocity: 1.0, options: [], animations: { self.center = originalCenter }) { (success) in delay(seconds: 0.1, completion: { self.bounceOff(point: point, morphSize: morphSize) }) } //至此,循环的头像碰撞运动动画已经完成

    //下面执行压缩动画

    let morphAnimation = CABasicAnimation(keyPath: “path”) morphAnimation.duration = animationDuration morphAnimation.toValue = UIBezierPath(ovalIn: morphedFrame).cgPath

    morphAnimation.timingFunction = CAMediaTimingFunction( name: kCAMediaTimingFunctionEaseOut)

    circleLayer.add(morphAnimation, forKey: nil) //如若只实现上述代码,那只是白色的圈圈压缩了,而 photo 并没有变化,所以我们需要把遮罩层也添加一个动画 maskLayer.add(morphAnimaiton, forKey: nil)

iOS动画

Layer Animation(四)

Layer Animation(二)