index.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <template>
  2. <view class="defaultStyles">
  3. </view>
  4. </template>
  5. <script lang="uts">
  6. import Animator from 'android.animation.Animator'
  7. import TextUtils from 'android.text.TextUtils'
  8. import View from 'android.view.View'
  9. import LottieAnimationView from 'com.airbnb.lottie.LottieAnimationView'
  10. import LottieDrawable from 'com.airbnb.lottie.LottieDrawable'
  11. import FileInputStream from 'java.io.FileInputStream'
  12. class CustomAnimListener extends Animator.AnimatorListener {
  13. comp: UTSComponent < LottieAnimationView >
  14. constructor(com: UTSComponent < LottieAnimationView > ) {
  15. super();
  16. this.comp = com
  17. }
  18. override onAnimationStart(animation: Animator) {}
  19. override onAnimationEnd(animation: Animator, isReverse: Boolean) {
  20. this.comp.$emit("bindended")
  21. }
  22. override onAnimationEnd(animation: Animator) {}
  23. override onAnimationCancel(animation: Animator) {}
  24. override onAnimationRepeat(animation: Animator) {}
  25. }
  26. //原生提供以下属性或方法的实现
  27. export default {
  28. name: "animation-view",
  29. /**
  30. * 当播放到末尾时触发 ended 事件(自然播放结束会触发回调,循环播放结束及手动停止动画不会触发)
  31. */
  32. emits: ['bindended'],
  33. props: {
  34. /**
  35. * 动画资源地址,目前只支持绝对路径
  36. */
  37. "path": {
  38. type: String,
  39. default: ""
  40. },
  41. /**
  42. * 动画是否自动播放
  43. */
  44. "autoplay": {
  45. type: Boolean,
  46. default: false
  47. },
  48. /**
  49. * 动画是否循环播放
  50. */
  51. "loop": {
  52. type: Boolean,
  53. default: false
  54. },
  55. /**
  56. * 是否隐藏动画
  57. */
  58. "hidden": {
  59. type: Boolean,
  60. default: false
  61. },
  62. /**
  63. * 动画操作,可取值 play、pause、stop
  64. */
  65. "action": {
  66. type: String,
  67. default: "stop"
  68. }
  69. },
  70. data() {
  71. return {
  72. }
  73. },
  74. watch: {
  75. "path": {
  76. handler(newPath: string) {
  77. if(this.$el != null){
  78. let lottieAnimationView = this.$el!
  79. if (!TextUtils.isEmpty(newPath)) {
  80. if (newPath.startsWith("http://") || newPath.startsWith("https://")) {
  81. lottieAnimationView.setAnimationFromUrl(newPath)
  82. } else {
  83. // uni-app x 正式打包会放在asset中,需要特殊处理
  84. let realJsonPath = UTSAndroid.getResourcePath(newPath)
  85. if(realJsonPath.startsWith("/android_asset")){
  86. lottieAnimationView.setAnimation(realJsonPath.substring(15))
  87. }else{
  88. lottieAnimationView.setAnimation(new FileInputStream(realJsonPath),newPath)
  89. }
  90. }
  91. }
  92. if (this.autoplay) {
  93. lottieAnimationView.playAnimation()
  94. }
  95. }
  96. },
  97. immediate: false
  98. },
  99. "loop": {
  100. handler(newLoop: Boolean) {
  101. if(this.$el != null){
  102. if (newLoop) {
  103. this.$el!.repeatCount = Int.MAX_VALUE
  104. } else {
  105. // 不循环则设置成1次
  106. this.$el!.repeatCount = 0
  107. }
  108. if (this.autoplay) {
  109. this.$el!.playAnimation()
  110. }
  111. }
  112. },
  113. immediate: false
  114. },
  115. "autoplay": {
  116. handler(newValue: boolean) {
  117. if(this.$el != null){
  118. if (newValue) {
  119. this.$el!.playAnimation()
  120. }
  121. }
  122. },
  123. immediate: false
  124. },
  125. "action": {
  126. handler(newAction: string) {
  127. if (newAction == "play" || newAction == "pause" || newAction == "stop") {
  128. if(this.$el != null){
  129. if (this.action == "play") {
  130. this.$el!.playAnimation()
  131. } else if (this.action == "pause") {
  132. this.$el!.pauseAnimation()
  133. } else if (this.action == "stop") {
  134. this.$el!.cancelAnimation()
  135. this.$el!.clearAnimation()
  136. }
  137. }
  138. } else {
  139. // 非法入参,不管
  140. }
  141. },
  142. immediate: false
  143. },
  144. "hidden": {
  145. handler(newValue: boolean) {
  146. if(this.$el != null){
  147. if (newValue) {
  148. this.$el!.visibility = View.GONE
  149. } else {
  150. this.$el!.visibility = View.VISIBLE
  151. }
  152. }
  153. },
  154. immediate: false
  155. },
  156. },
  157. methods: {
  158. setRepeatMode(repeat: string) {
  159. if(this.$el != null){
  160. if ("RESTART" == repeat) {
  161. this.$el!.repeatMode = LottieDrawable.RESTART
  162. } else if ("REVERSE" == repeat) {
  163. this.$el!.repeatMode = LottieDrawable.RESTART
  164. }
  165. }
  166. },
  167. },
  168. NVLoad(): LottieAnimationView {
  169. let lottieAnimationView = new LottieAnimationView($androidContext)
  170. return lottieAnimationView
  171. },
  172. NVLoaded() {
  173. if(this.$el != null){
  174. this.$el!.repeatMode = LottieDrawable.RESTART;
  175. this.$el!.visibility = View.GONE
  176. this.$el!.repeatCount = 0
  177. this.$el!.addAnimatorListener(new CustomAnimListener(this))
  178. }
  179. }
  180. }
  181. </script>
  182. <style>
  183. /* 定义默认样式值, 组件使用者没有配置时使用 */
  184. .defaultStyles {
  185. width: 750rpx;
  186. height: 240rpx;
  187. }
  188. </style>