     func positionAnimationWillStart(anim: CABasicAnimation)
 }
 
+
+// UIView subclass that bends its edges (internally, a CAShapeLayer filled with `fillColor`) when its position changes.
+// You'll receive the best effect when you use `+animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:`
+// to animate the change of the position and set `damping` and `initialSpringVelocity` to different values
+// than in that animation block. I propose to use slightly lower values for these properties.
+// These properties can't be set automatically, because `CASpringAnimation` is private.
 class BendingView: UIView, BendingLayerDelegate {
 
     // MARK: Public properties
 
     var damping: CGFloat = 0.7
     var initialSpringVelocity: CGFloat = 0.8
-    var fillColor = UIColor(red: 0, green: 0.722, blue: 1, alpha: 1) // blue color
+    var fillColor: UIColor = UIColor(red: 0, green: 0.722, blue: 1, alpha: 1) {
+    didSet {
+        updateColor()
+    }
+    }
 
     // MARK: Private properties
 
     var displayLink: CADisplayLink?
     var animationCount = 0
+    // A hidden view that is used only for spring animation's simulation.
+    // Its frame's origin matches the view's frame origin (except during animation). Of course it is in a different coordinate system,
+    // but it doesn't matter to us. What we're interested in, is a position's difference between this subview's frame and the view's frame.
+    // This difference (`bendingOffset`) is used for bending the edges of the view.
     let dummyView = UIView()
     let shapeLayer = CAShapeLayer()
-
-    var bendingFactor: CGPoint = CGPointZero {
-        didSet {
-            updatePath()
-        }
+    var bendingOffset: UIOffset = UIOffsetZero {
+    didSet {
+        updatePath()
     }
-
-    var path: UIBezierPath {
-        get {
-            var frame: CGRect
-            if let presentationLayer = layer.presentationLayer() as? CALayer {
-                frame = presentationLayer.frame
-            } else {
-                frame = self.frame
-            }
-            let width = CGRectGetWidth(frame)
-            let height = CGRectGetHeight(frame)
-
-            let path = UIBezierPath()
-            path.moveToPoint(CGPoint(x: 0, y: 0))
-            path.addQuadCurveToPoint(CGPoint(x: width, y: 0),
-                controlPoint:CGPoint(x: width / 2.0, y: 0 + bendingFactor.y))
-            path.addQuadCurveToPoint(CGPoint(x: width, y: height),
-                controlPoint:CGPoint(x: width + bendingFactor.x, y: height / 2.0))
-            path.addQuadCurveToPoint(CGPoint(x: 0, y: height),
-                controlPoint: CGPoint(x: width / 2.0, y: height + bendingFactor.y))
-            path.addQuadCurveToPoint(CGPoint(x: 0, y: 0),
-                controlPoint: CGPoint(x: bendingFactor.x, y: height / 2.0))
-            path.closePath()
-
-            return path
-        }
     }
 
     // MARK: Init

    override func addAnimation(anim: CAAnimation!, forKey key: String!) {
        super.addAnimation(anim, forKey: key)

        if let basicAnimation = anim as? CABasicAnimation {
            if basicAnimation.keyPath == NSStringFromSelector("position") {
                self.delegate?.positionAnimationWillStart?(basicAnimation)


        let newPosition = layer.frame.origin

        // Effects of this animation are invisible, because dummyView is hidden.
        // dummyView frame's change animation matches the animation of the whole view, though it's in a different coordinate system.
        UIView.animateWithDuration(anim.duration,
            delay: anim.beginTime,
            usingSpringWithDamping: damping,
