animate.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. 动画函数 animate (obj,attrObj,dur,fun,callback)
  3. obj 要动画的对象
  4. attrobj 要动画的属性对象{width:xxxx,height:xxx,left:xxxx,top:xxxx,opacity:xxx}
  5. dur 持续时间
  6. fun 动画方式
  7. callback 变化完成之后要处理的内容
  8. */
  9. /*
  10. 函数 colorAnimate (obj,attr,val,dur,fn,callback)
  11. obj 要处理的对象
  12. attr 要处理的属性 background color
  13. val 最终颜色 rbg #
  14. fn 动画的方式
  15. callback 变化完成之后要处理的内容
  16. */
  17. //动画算法
  18. /*
  19. Linear:无缓动效果(匀速运动);
  20. Quad:二次方的缓动;
  21. Cubic:三次方的缓动
  22. Quartic:四次方的缓动;
  23. Quintic:五次方的缓动;
  24. Sinusoidal:正弦曲线的缓动;
  25. Exponential:指数曲线的缓动;
  26. Circular:圆形曲线的缓动;
  27. Elastic:指数衰减的正弦曲线缓动;
  28. Back:超过范围的三次方缓动);
  29. Bounce:指数衰减的反弹缓动。
  30. 每个效果都分三个缓动方式(方法),分别是:
  31. easeIn:从0开始加速的运动;
  32. easeOut:减速到0的运动;
  33. easeInOut:前半段从0开始加速,后半段减速到0的运动。
  34. 函数的四个参数分别代表:
  35. t--- current time(当前时间);0 +=60
  36. b--- beginning value(初始值);100
  37. c--- change in value(变化量);500-100
  38. d---duration(持续时间) 5000
  39. Tween.Quad.easeInt()
  40. 运算的结果就是当前的运动路程。
  41. 整理翻译:Code宝宝
  42. 翻译或解释不对的地方希望各位修正、批评。
  43. 50
  44. Tween.Linear
  45. Tween.Quad.easeIn
  46. */
  47. const Tween = {
  48. Linear: function(t, b, c, d) {
  49. return (c * t) / d + b
  50. },
  51. Quad: {
  52. easeIn: function(t, b, c, d) {
  53. return c * (t /= d) * t + b
  54. },
  55. easeOut: function(t, b, c, d) {
  56. return -c * (t /= d) * (t - 2) + b
  57. },
  58. easeInOut: function(t, b, c, d) {
  59. if ((t /= d / 2) < 1) return (c / 2) * t * t + b
  60. return (-c / 2) * (--t * (t - 2) - 1) + b
  61. },
  62. },
  63. Cubic: {
  64. easeIn: function(t, b, c, d) {
  65. return c * (t /= d) * t * t + b
  66. },
  67. easeOut: function(t, b, c, d) {
  68. return c * ((t = t / d - 1) * t * t + 1) + b
  69. },
  70. easeInOut: function(t, b, c, d) {
  71. if ((t /= d / 2) < 1) return (c / 2) * t * t * t + b
  72. return (c / 2) * ((t -= 2) * t * t + 2) + b
  73. },
  74. },
  75. Quart: {
  76. easeIn: function(t, b, c, d) {
  77. return c * (t /= d) * t * t * t + b
  78. },
  79. easeOut: function(t, b, c, d) {
  80. return -c * ((t = t / d - 1) * t * t * t - 1) + b
  81. },
  82. easeInOut: function(t, b, c, d) {
  83. if ((t /= d / 2) < 1) return (c / 2) * t * t * t * t + b
  84. return (-c / 2) * ((t -= 2) * t * t * t - 2) + b
  85. },
  86. },
  87. Quint: {
  88. easeIn: function(t, b, c, d) {
  89. return c * (t /= d) * t * t * t * t + b
  90. },
  91. easeOut: function(t, b, c, d) {
  92. return c * ((t = t / d - 1) * t * t * t * t + 1) + b
  93. },
  94. easeInOut: function(t, b, c, d) {
  95. if ((t /= d / 2) < 1) return (c / 2) * t * t * t * t * t + b
  96. return (c / 2) * ((t -= 2) * t * t * t * t + 2) + b
  97. },
  98. },
  99. Sine: {
  100. easeIn: function(t, b, c, d) {
  101. return -c * Math.cos((t / d) * (Math.PI / 2)) + c + b
  102. },
  103. easeOut: function(t, b, c, d) {
  104. return c * Math.sin((t / d) * (Math.PI / 2)) + b
  105. },
  106. easeInOut: function(t, b, c, d) {
  107. return (-c / 2) * (Math.cos((Math.PI * t) / d) - 1) + b
  108. },
  109. },
  110. Expo: {
  111. easeIn: function(t, b, c, d) {
  112. return t == 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b
  113. },
  114. easeOut: function(t, b, c, d) {
  115. return t == d ? b + c : c * (-Math.pow(2, (-10 * t) / d) + 1) + b
  116. },
  117. easeInOut: function(t, b, c, d) {
  118. if (t == 0) return b
  119. if (t == d) return b + c
  120. if ((t /= d / 2) < 1) return (c / 2) * Math.pow(2, 10 * (t - 1)) + b
  121. return (c / 2) * (-Math.pow(2, -10 * --t) + 2) + b
  122. },
  123. },
  124. Circ: {
  125. easeIn: function(t, b, c, d) {
  126. return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b
  127. },
  128. easeOut: function(t, b, c, d) {
  129. return c * Math.sqrt(1 - (t = t / d - 1) * t) + b
  130. },
  131. easeInOut: function(t, b, c, d) {
  132. if ((t /= d / 2) < 1) return (-c / 2) * (Math.sqrt(1 - t * t) - 1) + b
  133. return (c / 2) * (Math.sqrt(1 - (t -= 2) * t) + 1) + b
  134. },
  135. },
  136. Elastic: {
  137. easeIn: function(t, b, c, d, a, p) {
  138. if (t == 0) return b
  139. if ((t /= d) == 1) return b + c
  140. if (!p) p = d * 0.3
  141. if (!a || a < Math.abs(c)) {
  142. a = c
  143. var s = p / 4
  144. } else var s = (p / (2 * Math.PI)) * Math.asin(c / a)
  145. return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin(((t * d - s) * (2 * Math.PI)) / p)) + b
  146. },
  147. easeOut: function(t, b, c, d, a, p) {
  148. if (t == 0) return b
  149. if ((t /= d) == 1) return b + c
  150. if (!p) p = d * 0.3
  151. if (!a || a < Math.abs(c)) {
  152. a = c
  153. var s = p / 4
  154. } else var s = (p / (2 * Math.PI)) * Math.asin(c / a)
  155. return a * Math.pow(2, -10 * t) * Math.sin(((t * d - s) * (2 * Math.PI)) / p) + c + b
  156. },
  157. easeInOut: function(t, b, c, d, a, p) {
  158. if (t == 0) return b
  159. if ((t /= d / 2) == 2) return b + c
  160. if (!p) p = d * (0.3 * 1.5)
  161. if (!a || a < Math.abs(c)) {
  162. a = c
  163. var s = p / 4
  164. } else var s = (p / (2 * Math.PI)) * Math.asin(c / a)
  165. if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin(((t * d - s) * (2 * Math.PI)) / p)) + b
  166. return a * Math.pow(2, -10 * (t -= 1)) * Math.sin(((t * d - s) * (2 * Math.PI)) / p) * 0.5 + c + b
  167. },
  168. },
  169. Back: {
  170. easeIn: function(t, b, c, d, s) {
  171. if (s == undefined) s = 1.70158
  172. return c * (t /= d) * t * ((s + 1) * t - s) + b
  173. },
  174. easeOut: function(t, b, c, d, s) {
  175. if (s == undefined) s = 1.70158
  176. return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b
  177. },
  178. easeInOut: function(t, b, c, d, s) {
  179. if (s == undefined) s = 1.70158
  180. if ((t /= d / 2) < 1) return (c / 2) * (t * t * (((s *= 1.525) + 1) * t - s)) + b
  181. return (c / 2) * ((t -= 2) * t * (((s *= 1.525) + 1) * t + s) + 2) + b
  182. },
  183. },
  184. Bounce: {
  185. easeIn: function(t, b, c, d) {
  186. return c - Tween.Bounce.easeOut(d - t, 0, c, d) + b
  187. },
  188. easeOut: function(t, b, c, d) {
  189. if ((t /= d) < 1 / 2.75) {
  190. return c * (7.5625 * t * t) + b
  191. } else if (t < 2 / 2.75) {
  192. return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b
  193. } else if (t < 2.5 / 2.75) {
  194. return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b
  195. } else {
  196. return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b
  197. }
  198. },
  199. easeInOut: function(t, b, c, d) {
  200. if (t < d / 2) return Tween.Bounce.easeIn(t * 2, 0, c, d) * 0.5 + b
  201. else return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b
  202. },
  203. },
  204. }
  205. /*
  206. 动画函数 animate (obj,attrObj,dur,fun,callback)
  207. obj 要动画的对象
  208. attrobj 要动画的属性对象{width:xxxx,height:xxx,left:xxxx,top:xxxx,opacity:xxx}
  209. dur 持续时间
  210. fun 动画方式
  211. callback 回调函数
  212. */
  213. export function animate(obj, attrObj, dur, fun, callback) {
  214. clearInterval(obj.t)
  215. if (arguments.length == 2) {
  216. dur = 500
  217. fun = Tween.Linear
  218. callback = null
  219. }
  220. if (arguments.length == 3) {
  221. if (typeof dur == 'number') {
  222. dur = dur
  223. fun = Tween.Linear
  224. callback = null
  225. }
  226. if (typeof dur == 'function') {
  227. if (dur.length >= 4) {
  228. fun = dur
  229. callback = null
  230. dur = 500
  231. } else {
  232. fun = Tween.Linear
  233. callback = dur
  234. dur = 500
  235. }
  236. }
  237. }
  238. if (arguments.length == 4) {
  239. if (typeof dur == 'number') {
  240. dur = dur
  241. if (fun.length >= 4) {
  242. fun = fun
  243. callback = null
  244. } else {
  245. callback = fun
  246. fun = Tween.Linear
  247. }
  248. } else {
  249. callback = fun
  250. fun = dur
  251. dur = 500
  252. }
  253. }
  254. var time = 0
  255. var start = {}
  256. var change = {}
  257. for (var i in attrObj) {
  258. start[i] = setCss(obj, i)
  259. change[i] = attrObj[i] - start[i]
  260. }
  261. obj.t = setInterval(function() {
  262. if (time >= dur) {
  263. clearInterval(obj.t)
  264. for (var i in attrObj) {
  265. setCss(obj, i, attrObj[i])
  266. }
  267. if (callback) {
  268. callback.call(obj)
  269. }
  270. } else {
  271. for (var i in attrObj) {
  272. setCss(obj, i, fun(time, start[i], change[i], dur))
  273. }
  274. time += 60
  275. }
  276. }, 60)
  277. }
  278. function setCss(obj, attr, val) {
  279. if (obj.nodeType !== 1) {
  280. return
  281. }
  282. //初始化参数
  283. var attr = attr.replace(/^\s*|\s*$/g, '')
  284. //获取值
  285. if (arguments.length == 2) {
  286. //位置和尺寸
  287. if (attr == 'height' || attr == 'width' || attr == 'top' || attr == 'left' || attr == 'right' || attr == 'bottom') {
  288. var val = obj.currentStyle ? parseInt(obj.currentStyle[attr]) : parseInt(getComputedStyle(obj, null)[attr])
  289. if (!val) {
  290. var str = 'offset' + attr.replace(attr.charAt(0), attr.charAt(0).toUpperCase())
  291. val = obj[str]
  292. }
  293. return val
  294. }
  295. if (
  296. attr == 'padding' ||
  297. attr == 'margin' ||
  298. attr == 'paddingTop' ||
  299. attr == 'paddingLeft' ||
  300. attr == 'paddingRight' ||
  301. attr == 'paddingBottom' ||
  302. attr == 'marginTop' ||
  303. attr == 'marginLeft' ||
  304. attr == 'marginRight' ||
  305. attr == 'marginBottom'
  306. ) {
  307. var cc = parseInt(
  308. obj.currentStyle
  309. ? obj.currentStyle[attr] == undefined || obj.currentStyle[attr] == 'auto'
  310. ? 0
  311. : obj.currentStyle[attr]
  312. : getComputedStyle(obj, null)[attr] == undefined
  313. ? 0
  314. : getComputedStyle(obj, null)[attr]
  315. )
  316. return cc
  317. }
  318. //透明度
  319. if (attr == 'opacity') {
  320. return obj.currentStyle ? parseFloat(obj.currentStyle[attr] || 1) : parseFloat(getComputedStyle(obj, null)[attr] || 1)
  321. }
  322. //颜色
  323. if (
  324. attr == 'color' ||
  325. attr == 'background' ||
  326. attr == 'backgroundColor' ||
  327. attr == 'borderBottomColor' ||
  328. attr == 'borderLeftColor' ||
  329. attr == 'borderRightColor' ||
  330. attr == 'borderTopColor'
  331. ) {
  332. var colors = obj.currentStyle ? obj.currentStyle[attr] || '#000000' : getComputedStyle(obj, null)[attr] || '#000000'
  333. //获取对象
  334. return getColor(colors)
  335. }
  336. if (attr == 'scrollTop') {
  337. return obj.scrollTop
  338. }
  339. return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, null)[attr]
  340. } else if (arguments.length == 3) {
  341. switch (attr) {
  342. case 'width':
  343. case 'height':
  344. case 'top':
  345. case 'left':
  346. case 'bottom':
  347. case 'right':
  348. case 'padding':
  349. case 'margin':
  350. case 'paddingLeft':
  351. case 'paddingRight':
  352. case 'paddingTop':
  353. case 'paddingBottom':
  354. case 'marginLeft':
  355. case 'marginRight':
  356. case 'marginTop':
  357. case 'marginBottom':
  358. obj.style[attr] = val + 'px'
  359. break
  360. case 'opacity':
  361. obj.style[attr] = val
  362. obj.style.filter = 'alpha(opacity=' + val * 100 + ')'
  363. break
  364. case 'scrollTop':
  365. obj.scrollTop = val
  366. break
  367. case 'color':
  368. case 'background':
  369. case 'backgroundColor':
  370. case 'borderBottomColor':
  371. case 'borderLeftColor':
  372. case 'borderRightColor':
  373. case 'borderTopColor':
  374. obj.style[attr] = val
  375. break
  376. default:
  377. obj.style[attr] = val
  378. }
  379. }
  380. }
  381. //颜色渐变动画
  382. //获得颜色
  383. function getColor(color) {
  384. var str, r, g, b, arr
  385. if (typeof color == 'string') {
  386. //16 进制
  387. if (color.charAt(0) === '#') {
  388. str = color.substring(1)
  389. r = parseInt(str.substr(0, 2), 16)
  390. g = parseInt(str.substr(2, 2), 16)
  391. b = parseInt(str.substr(4, 2), 16)
  392. arr = [r, g, b]
  393. return arr
  394. } else {
  395. str = color.substring(4, color.length - 1)
  396. return str.split(',')
  397. }
  398. }
  399. if (color instanceof Array) {
  400. return color
  401. }
  402. }