iOS 動畫十一:Shapes and Masks

在我們創(chuàng)建想要的形狀之后,我們可以將這些屬性設置為 stroke color, ?ll color 和stroke dash pattern。

我們可以對這些屬性進行動畫:
? path: 漸變 layer 的形狀為其它樣子。
? fillColor: 將 shape 的填充色改為不同的顏色。
? lineDashPhase: 在你的形狀周圍創(chuàng)建一個 marquee 或 “marching ants” 效果
? lineWidth: 增加或縮小你的線條的線條尺寸。

現(xiàn)在我們實現(xiàn)一個小例子,例子最后效果是這樣的:

代碼實現(xiàn)
avatar view

? photoLayer: avatar image layer
? circleLayer: 畫圓 layer
? maskLayer: mask layer
? label: player’s name label

bounce-off animation
bounce-off animation
func searchForOpponent() {
    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)

    delay(seconds: 4.0, completion: foundOpponent)
  }

  func foundOpponent() {
    status.text = "Connecting..."

    opponentAvatar.image = UIImage(named: "avatar-2")
    opponentAvatar.name = "Ray"

    delay(seconds: 4.0, completion: connectedToOpponent)
  }

  func connectedToOpponent() {
    myAvatar.shouldTransitionToFinishedState = true
    opponentAvatar.shouldTransitionToFinishedState = true

    delay(seconds: 1.0, completion: completed)
  }

  func completed() {
    status.text = "Ready to play"
    UIView.animate(withDuration: 0.2) {
      self.vs.alpha = 1.0
      self.searchAgain.alpha = 1.0
    }
  }
Morphing shapes 形狀漸變

當兩個 avatars 相撞時,它們應該在這個完全彈性碰撞中稍微擠壓一下。視圖控制器將通過一個 morph size,使頭像形狀變得稍高和稍窄的效果,如圖所示:

Morphing shapes

這樣,當他們在屏幕中間相遇時,看起來頭像互相擠壓。

核心代碼:

 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
      if self.shouldTransitionToFinishedState {
        self.animateToSquare()
      }
    })

    UIView.animate(withDuration: animationDuration,
                   delay: animationDuration,
                  usingSpringWithDamping: 0.7,
                   initialSpringVelocity: 1.0,
                   animations: {
        self.center = originalCenter
    }, completion: { _ in
      delay(seconds: 0.1) {
        if !self.isSquare {
          self.bounceOff(point: point, morphSize: morphSize)
        }
      }
    })

    let morphedFrame = (originalCenter.x > point.x) ?

      CGRect(x: 0.0, y: bounds.height - morphSize.height,
             width: morphSize.width, height: morphSize.height):

      CGRect(x: bounds.width - morphSize.width,
             y: bounds.height - morphSize.height,
             width: morphSize.width, height: morphSize.height)

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

    morphAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

    circleLayer.add(morphAnimation, forKey: nil)
    maskLayer.add(morphAnimation, forKey: nil)
  }

demo下載

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容