• Linear:无缓动效果
    • Quadratic:二次方的缓动(t^2)
    • Cubic:三次方的缓动(t^3)
    • Quartic:四次方的缓动(t^4)
    • Quintic:五次方的缓动(t^5)
    • Sinusoidal:正弦曲线的缓动(sin(t))
    • Exponential:指数曲线的缓动(2^t)
    • Circular:圆形曲线的缓动(sqrt(1-t^2))
    • Elastic:指数衰减的正弦曲线缓动
    • 超过范围的三次方缓动((s+1)t^3 – st^2)
    • 指数衰减的反弹缓动

    每个效果都分三个缓动方式,分别是:

    • easeIn:从0开始加速,先慢后快;
    • easeOut:减速到0,先快后慢;
    • easeInOut:前半段从0开始加速,后半段减速到0,先慢后快然后再慢;

    缓动动画算法 - 图1

    1. /*
    2. * Tween.js
    3. * t: current time(当前时间)
    4. * b: beginning value(初始值)
    5. * c: change in value(变化量)
    6. * d: duration(持续时间)
    7. * you can visit 'https://www.zhangxinxu.com/study/201612/how-to-use-tween-js.html' to get effect
    8. */
    9. var Tween = {
    10. Linear: function(t, b, c, d) { return c*t/d + b; },
    11. Quad: {
    12. easeIn: function(t, b, c, d) {
    13. return c * (t /= d) * t + b;
    14. },
    15. easeOut: function(t, b, c, d) {
    16. return -c *(t /= d)*(t-2) + b;Bounce
    17. },
    18. easeInOut: function(t, b, c, d) {
    19. if ((t /= d / 2) < 1) return c / 2 * t * t + b;
    20. return -c / 2 * ((--t) * (t-2) - 1) + b;
    21. }
    22. },
    23. Cubic: {
    24. easeIn: function(t, b, c, d) {
    25. return c * (t /= d) * t * t + b;
    26. },
    27. easeOut: function(t, b, c, d) {
    28. return c * ((t = t/d - 1) * t * t + 1) + b;
    29. },
    30. easeInOut: function(t, b, c, d) {
    31. if ((t /= d / 2) < 1) return c / 2 * t * t*t + b;
    32. return c / 2*((t -= 2) * t * t + 2) + b;
    33. }
    34. },
    35. Quart: {
    36. easeIn: function(t, b, c, d) {
    37. return c * (t /= d) * t * t*t + b;
    38. },
    39. easeOut: function(t, b, c, d) {
    40. return -c * ((t = t/d - 1) * t * t*t - 1) + b;
    41. },
    42. easeInOut: function(t, b, c, d) {
    43. if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
    44. return -c / 2 * ((t -= 2) * t * t*t - 2) + b;
    45. }
    46. },
    47. Quint: {
    48. easeIn: function(t, b, c, d) {
    49. return c * (t /= d) * t * t * t * t + b;
    50. },
    51. easeOut: function(t, b, c, d) {
    52. return c * ((t = t/d - 1) * t * t * t * t + 1) + b;
    53. },
    54. easeInOut: function(t, b, c, d) {
    55. if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
    56. return c / 2*((t -= 2) * t * t * t * t + 2) + b;
    57. }
    58. },
    59. Sine: {
    60. easeIn: function(t, b, c, d) {
    61. return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
    62. },
    63. easeOut: function(t, b, c, d) {
    64. return c * Math.sin(t/d * (Math.PI/2)) + b;
    65. },
    66. easeInOut: function(t, b, c, d) {
    67. return -c / 2 * (Math.cos(Math.PI * t/d) - 1) + b;
    68. }
    69. },
    70. Expo: {
    71. easeIn: function(t, b, c, d) {
    72. return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
    73. },
    74. easeOut: function(t, b, c, d) {
    75. return (t==d) ? b + c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
    76. },
    77. easeInOut: function(t, b, c, d) {
    78. if (t==0) return b;
    79. if (t==d) return b+c;
    80. if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
    81. return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
    82. }
    83. },
    84. Circ: {
    85. easeIn: function(t, b, c, d) {
    86. return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
    87. },
    88. easeOut: function(t, b, c, d) {
    89. return c * Math.sqrt(1 - (t = t/d - 1) * t) + b;
    90. },
    91. easeInOut: function(t, b, c, d) {
    92. if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
    93. return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
    94. }
    95. },
    96. Elastic: {
    97. easeIn: function(t, b, c, d, a, p) {
    98. var s;
    99. if (t==0) return b;
    100. if ((t /= d) == 1) return b + c;
    101. if (typeof p == "undefined") p = d * .3;
    102. if (!a || a < Math.abs(c)) {
    103. s = p / 4;
    104. a = c;
    105. } else {
    106. s = p / (2 * Math.PI) * Math.asin(c / a);
    107. }
    108. return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
    109. },
    110. easeOut: function(t, b, c, d, a, p) {
    111. var s;
    112. if (t==0) return b;
    113. if ((t /= d) == 1) return b + c;
    114. if (typeof p == "undefined") p = d * .3;
    115. if (!a || a < Math.abs(c)) {
    116. a = c;
    117. s = p / 4;
    118. } else {
    119. s = p/(2*Math.PI) * Math.asin(c/a);
    120. }
    121. return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
    122. },
    123. easeInOut: function(t, b, c, d, a, p) {
    124. var s;
    125. if (t==0) return b;
    126. if ((t /= d / 2) == 2) return b+c;
    127. if (typeof p == "undefined") p = d * (.3 * 1.5);
    128. if (!a || a < Math.abs(c)) {
    129. a = c;
    130. s = p / 4;
    131. } else {
    132. s = p / (2 *Math.PI) * Math.asin(c / a);
    133. }
    134. if (t < 1) return -.5 * (a * Math.pow(2, 10* (t -=1 )) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
    135. return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p ) * .5 + c + b;
    136. }
    137. },
    138. Back: {
    139. easeIn: function(t, b, c, d, s) {
    140. if (typeof s == "undefined") s = 1.70158;
    141. return c * (t /= d) * t * ((s + 1) * t - s) + b;
    142. },
    143. easeOut: function(t, b, c, d, s) {
    144. if (typeof s == "undefined") s = 1.70158;
    145. return c * ((t = t/d - 1) * t * ((s + 1) * t + s) + 1) + b;
    146. },
    147. easeInOut: function(t, b, c, d, s) {
    148. if (typeof s == "undefined") s = 1.70158;
    149. if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
    150. return c / 2*((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
    151. }
    152. },
    153. Bounce: {
    154. easeIn: function(t, b, c, d) {
    155. return c - Tween.Bounce.easeOut(d-t, 0, c, d) + b;
    156. },
    157. easeOut: function(t, b, c, d) {
    158. if ((t /= d) < (1 / 2.75)) {
    159. return c * (7.5625 * t * t) + b;
    160. } else if (t < (2 / 2.75)) {
    161. return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
    162. } else if (t < (2.5 / 2.75)) {
    163. return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
    164. } else {
    165. return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
    166. }
    167. },
    168. easeInOut: function(t, b, c, d) {
    169. if (t < d / 2) {
    170. return Tween.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
    171. } else {
    172. return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
    173. }
    174. }
    175. }
    176. }
    177. Math.tween = Tween;

    实例: 小球落地效果
    核心代码

    1. funFall = function() {
    2. var start = 0, during = 100;
    3. var _run = function() {
    4. start++;
    5. var top = Tween.Bounce.easeOut(start, objBall.top, 500 - objBall.top, during);
    6. ball.css("top", top);
    7. shadowWithBall(top); // 投影跟随小球的动
    8. if (start < during) requestAnimationFrame(_run);
    9. };
    10. _run();
    11. };