createAnimation.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // const defaultOption = {
  2. // duration: 300,
  3. // timingFunction: 'linear',
  4. // delay: 0,
  5. // transformOrigin: '50% 50% 0'
  6. // }
  7. // #ifdef APP-NVUE
  8. const nvueAnimation = uni.requireNativePlugin('animation')
  9. // #endif
  10. class MPAnimation {
  11. constructor(options, _this) {
  12. this.options = options
  13. // 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误
  14. this.animation = uni.createAnimation({
  15. ...options
  16. })
  17. this.currentStepAnimates = {}
  18. this.next = 0
  19. this.$ = _this
  20. }
  21. _nvuePushAnimates(type, args) {
  22. let aniObj = this.currentStepAnimates[this.next]
  23. let styles = {}
  24. if (!aniObj) {
  25. styles = {
  26. styles: {},
  27. config: {}
  28. }
  29. } else {
  30. styles = aniObj
  31. }
  32. if (animateTypes1.includes(type)) {
  33. if (!styles.styles.transform) {
  34. styles.styles.transform = ''
  35. }
  36. let unit = ''
  37. if(type === 'rotate'){
  38. unit = 'deg'
  39. }
  40. styles.styles.transform += `${type}(${args+unit}) `
  41. } else {
  42. styles.styles[type] = `${args}`
  43. }
  44. this.currentStepAnimates[this.next] = styles
  45. }
  46. _animateRun(styles = {}, config = {}) {
  47. let ref = this.$.$refs['ani'].ref
  48. if (!ref) return
  49. return new Promise((resolve, reject) => {
  50. nvueAnimation.transition(ref, {
  51. styles,
  52. ...config
  53. }, res => {
  54. resolve()
  55. })
  56. })
  57. }
  58. _nvueNextAnimate(animates, step = 0, fn) {
  59. let obj = animates[step]
  60. if (obj) {
  61. let {
  62. styles,
  63. config
  64. } = obj
  65. this._animateRun(styles, config).then(() => {
  66. step += 1
  67. this._nvueNextAnimate(animates, step, fn)
  68. })
  69. } else {
  70. this.currentStepAnimates = {}
  71. typeof fn === 'function' && fn()
  72. this.isEnd = true
  73. }
  74. }
  75. step(config = {}) {
  76. // #ifndef APP-NVUE
  77. this.animation.step(config)
  78. // #endif
  79. // #ifdef APP-NVUE
  80. this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
  81. this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
  82. this.next++
  83. // #endif
  84. return this
  85. }
  86. run(fn) {
  87. // #ifndef APP-NVUE
  88. this.$.animationData = this.animation.export()
  89. this.$.timer = setTimeout(() => {
  90. typeof fn === 'function' && fn()
  91. }, this.$.durationTime)
  92. // #endif
  93. // #ifdef APP-NVUE
  94. this.isEnd = false
  95. let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
  96. if(!ref) return
  97. this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
  98. this.next = 0
  99. // #endif
  100. }
  101. }
  102. const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
  103. 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
  104. 'translateZ'
  105. ]
  106. const animateTypes2 = ['opacity', 'backgroundColor']
  107. const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
  108. animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
  109. MPAnimation.prototype[type] = function(...args) {
  110. // #ifndef APP-NVUE
  111. this.animation[type](...args)
  112. // #endif
  113. // #ifdef APP-NVUE
  114. this._nvuePushAnimates(type, args)
  115. // #endif
  116. return this
  117. }
  118. })
  119. export function createAnimation(option, _this) {
  120. if(!_this) return
  121. clearTimeout(_this.timer)
  122. return new MPAnimation(option, _this)
  123. }