1 // ==========================================================================
  2 // Project:   SproutCore
  3 // Copyright: @2013 7x7 Software, Inc.
  4 // License:   Licensed under MIT license (see license.js)
  5 // ==========================================================================
  6 
  7 
  8 SC.mixin(SC.View,
  9   /** @scope SC.View */ {
 10 
 11   /** @class
 12 
 13     To modify the spring animation, you may set the following transition
 14     options in `transitionAdjustOptions`:
 15 
 16       - springs {Number} the number of spring back iterations.  Default: 4
 17       - springiness {Number} the spring coefficient.  Default: 0.25
 18       - duration {Number} the number of seconds for the animation.  Default: 0.4
 19 
 20     @extends SC.ViewTransitionProtocol
 21     @see SC.View#animate for other timing functions.
 22     @since Version 1.10
 23   */
 24   SPRING_ADJUST: {
 25 
 26     /** @private */
 27     run: function (view, options, finalLayout) {
 28       var springs = options.springs || 4,
 29         springiness = options.springiness || 0.25,
 30         layout = view.get('layout'),
 31         frames = [],
 32         frameCount = springs + 1,
 33         duration,
 34         i;
 35 
 36       // Split the duration evenly per frame.
 37       duration = options.duration || 0.4;
 38       duration = duration / frameCount;
 39 
 40       // Construct the frame layouts.
 41       for (i = 0; i < frameCount; i++) {
 42         if (i !== 0) {
 43           frames[i] = { value: SC.clone(finalLayout), duration: duration, timing: 'ease-in-out' };
 44         } else {
 45           frames[i] = { value: SC.clone(finalLayout), duration: duration, timing: 'ease-out' };
 46         }
 47       }
 48 
 49       // Adjust the spring frame layouts.
 50       for (var key in finalLayout) {
 51         var finalValue = finalLayout[key],
 52           // The spring is based on the "distance" to the final value and the springiness value.
 53           spring = Math.round((finalValue - layout[key]) * springiness);
 54 
 55         // Adjust the layout property for each spring.
 56         for (i = 0; i < springs; i++) {
 57           if (i % 2) {
 58             frames[i].value[key] = finalValue - spring; // Overshoot back.
 59           } else {
 60             frames[i].value[key] = finalValue + spring; // Overshoot forward.
 61           }
 62 
 63           // Cut back the spring amount after each spring
 64           spring = Math.round(spring * 0.5);
 65         }
 66       }
 67 
 68       var callback = function () {
 69         view.didTransitionAdjust();
 70       };
 71 
 72       // Animate through the frames.
 73       view._animateFrames(frames, callback, options.delay || 0);
 74     }
 75   }
 76 
 77 });
 78