     anim.isRemovedOnCompletion = false
     return anim
   }
-  
-  func applyAnimations(animations:[CAAnimation], to layer:CALayer, delay:TimeInterval, duration:TimeInterval){
-    let group = CAAnimationGroup()
-    if delay > 0{
-      group.beginTime = layer.convertTime(CACurrentMediaTime(), from: nil) + delay
-    }
-    group.duration = duration
-    group.fillMode = kCAFillModeBoth
-    group.isRemovedOnCompletion = false
-    group.animations = animations
-    layer.add(group, forKey: "hero")
-    layer.needsDisplayOnBoundsChange = true
-
-    self.animationGroups[layer] = (delay, group)
-  }
-  
-  func animate(view:UIView, appearing:Bool){
-    let snapshot = takeSnapshot(for: view)
-    let state = AnimationState(view: view, snapshot: snapshot, modifiers: context[view]!, appearing: appearing)
-    animationStates[view] = state
-
-    var maxDuration:TimeInterval = HeroDefaultAnimator.defaultAnimationDuration
-
-    var animations:[CAAnimation] = []
-    var contentViewAnims:[CAAnimation] = []
-
-    for (k, (fromValue, toValue)) in state.state{
+
+  init(view:UIView, snapshot:UIView, modifiers:HeroModifiers, appearing:Bool){
+    self.view = view
+    self.snapshot = snapshot
+    self.appearing = appearing
+    
+    for (key, param) in modifiers {
+      parameters[key] = param
+    }
+    
+    if let value = parameters["delay"]?.getFloat(0){
+      delay = TimeInterval(value)
+    }
+
+    let disappeared = viewState(for: view, with: modifiers)
+    for (key, disappearedState) in disappeared{
+      let appearingState = snapshot.layer.value(forKeyPath: key)
+      let toValue = appearing ? appearingState : disappearedState
+      let fromValue = !appearing ? appearingState : disappearedState
+      state[key] = (fromValue, toValue)
+    }
+    
+    let beginTime = snapshot.layer.convertTime(CACurrentMediaTime(), from: nil) + delay
+    
+    let contentLayer = snapshot.subviews[0].layer
+    for (k, (fromValue, toValue)) in state{
       let anim = animation(for:view, key: k, fromValue: fromValue, toValue: toValue)
-      maxDuration = max(maxDuration, anim.duration)
-      
-      animations.append(anim)
+      duration = max(duration, anim.duration)
+      anim.beginTime = beginTime
+
+      snapshot.layer.add(anim, forKey: k)
       if k == "cornerRadius"{
-        contentViewAnims.append(anim)
+        contentLayer.add(anim, forKey: k)
       } else {
         if k == "bounds.size"{
           let fromSize = (fromValue as! NSValue).cgSizeValue

      kanim.duration = duration
      kanim.timingFunctions = [timingFunction]
      anim = kanim
    } else if #available(iOS 9.0, *), key != "cornerRadius", let springOptions = context[view, "spring"] {
      let sanim = CASpringAnimation(keyPath: key)
      sanim.stiffness = (springOptions.getCGFloat(0) ?? 250)
      sanim.damping = (springOptions.getCGFloat(1) ?? 30)

  var snapshot:UIView
  var state = [String:(Any, Any)]()
  var appearing:Bool
  var delay:TimeInterval = 0
  var parameters = [String:[String]] ()
  var duration:TimeInterval = HeroDefaultAnimator.defaultAnimationDuration
  
  
  func getTimingFunction(for view:UIView) -> CAMediaTimingFunction{
    // get the timing function
    if let curveOptions = parameters["curve"]{
      if let c1 = curveOptions.getFloat(0),
        let c2 = curveOptions.getFloat(1),
        let c3 = curveOptions.getFloat(2),
